みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ややこしいコード

#include<iostream>
using namespace std;

int main() {
const int num = 5;
int test[num];

cout << num << "人の点数を入力して下さい。\n";
for (int i = 0; i < num; i++) {
cin >> test[i];

}


for (int s= 0; s < num - 1; s++) {
for (int t = s + 1; t < num; t++) {
if (test[t] > test[s]) {
int tmp = test[t];
test[t] = test[s];
test[s] = tmp;
}
}
}
for (int j = 0; j < num; j++) {
cout << j + 1 << "番目の人の点数は" << test[j] << "です。\n";
}

return 0;
}

配列を並べ替える(ソート)する練習コードなんですが、
ちょっとややこしいので解りやすく教えて欲しいです。
因みに点数は、
22,80,57,60,50の順でお願いします。

投稿日時 - 2018-07-19 21:20:25

QNo.9519841

困ってます

質問者が選んだベストアンサー

〉for (int s= 0; s < num - 1; s++)
〉for (int t = s + 1; t < num; t++)

外側のforループは何個目を比較元にするかのループです。
初期値か「0」ですからtest[0]、つまり配列testの一番目からスタートすることになります。
繰り返す回数は「num-1」なので、numの値である5から1引いた4未満(s<4)、増分値はインクリメント(s++)なので1ですから、0~3の4回繰り返すことになります。
なぜ配列は5個(0~4)なのに、num-1で4にしているかと言うと、配列の5番目は最後なので、比較する次の値がありません。よって比較する必要が無いためです。

内側のforループは、比較先が何個目かを決めるループです。
初期値は「s+1」ですから、比較元の一つ隣になります。
繰り返す回数は「num」ですから5未満。
ここでアレ?って思いませんか?
さっきは「num-1」でしたよね?
理由は簡単です。比較先は「s+1」なのですから、上限も「num-1+1」。つまり「num」となります。

ループがスタートすると
一回目はs=0 t=s+1=1を比較。
test[1]>test[0]なら、二つの値を入れ替えます。

次にtがインクリメントし
s=0 t=1+1=2となり、test[0]とtest[2]を比較。
test[2]>test[0]なら、入れ替えます。

これを上限(5未満)、つまりtest[4]まで比較します。
これで「配列の一番目に一番大きい数字をもってくる」ことになります。

内側のループが最後まで行ったら、今度はsがインクリメントしs=0+1=1、内側のループは初期値t=s+1=2から再びスタートします。
よって今度は、test[1]とtest[2]~[4]を比較することになり、「配列の二番目に二番目に大きい数字をもってくる」ことになります。

これをsが上限の(4未満=3)まで繰り返すことで、「配列の四番目に四番目に大きい数字をもってくる」ことによって、「五番目は一番小さい数字」になります。

投稿日時 - 2018-07-20 01:07:09

お礼

回答ありがとうございます
非常に複雑でしたが何とか理解しました;
詳しく細かく懇切丁寧に教えて頂きありがとうございました!!

投稿日時 - 2018-07-20 12:35:47

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

>配列を並べ替える(ソート)する練習コードなんですが、
>ちょっとややこしいので解りやすく教えて欲しいです。
回答No.1のお礼に下記のような記述があります。
----------ここから----------
正直に申しますと、
for (int s= 0; s < num - 1; s++)
for (int t = s + 1; t < num; t++)
ここの部分がよく解っておりません;
----------ここまで----------
この部分と言われてもforループ基本的な動作は理解されていますよね?
forループの中にforループがある理由が分からないのでしょうか?
配列変数の各要素の値をソートするときはforループの入れ子構造(多重構造)はありふれた手法なのでややこしいことではありません。
寧ろ、ループの中で値の比較と入れ替えをどのようにしているかを理解する必要があるでしょう。
配列変数のtestは5個の箱が連結していると考えれば其々の箱に番号は付いています。(test[0]、test[1]、test[2]、test[3]、test[4])
これを順番に比較対象にするためには[]内の番号を順次入れ替えて比較すれば同じ数式で繰り返すことでプログラムを簡素化できます。
test[1]>test[0]のときtest[1]をtmpへ代入し、test[0]をtest[1]へ代入し、tmpをtest[0]へ代入すればtest[1]とtest[0]を入れ替えたことになります。
この操作をtest[t]とtest[s]と言う形に置き換えればsとtの値を順次変更しながら配列変数内の値を大きい順に並べ変えられます。
sとtの値を順次変化させる手法としてforループを2重に設けてすべての組み合わせをチェックして並び替えています。
外側のforループは変数がsで0から3までの4回繰り返します。
内側のforループは変数がtでs+1から4までの繰り返しですがs=0のときはtが1から4まで4回、S=1のときはtが2から4まで3回、s=2のときはtが3から4まで2回、s=3のときはtが4だけの1回で合計10回の比較が行われます。
これらの動作の内、何がややこしいのでしょう?

投稿日時 - 2018-07-20 13:06:39

お礼

回答ありがとうございます。
ちょっとfor文の値を勘違いしていたみたいです。
for (int t = s + 1; t < num; t++)
の所のs+1の所を最初の所がsの部分が1だと思ってました・・・;

投稿日時 - 2018-07-20 14:28:33

ANo.5

sを使ったループで何をしたいかというと、sより前の要素がソート済みになっているようにしたいのです。
そう仮定すると、s以降の要素について処理するだけですみます。
で、s以降の要素をどうするといいかというと、その中で最も小さい要素がsの位置に来るように並べ替えればいいのです。これがtを使ったループで行っている処理です。
それがうまくいったら、sを1つずらして同じ作業を繰り返します。

投稿日時 - 2018-07-20 09:53:04

お礼

回答ありがとうございます。

投稿日時 - 2018-07-20 12:27:44

ANo.3

22,80,57,60,50
一個目と比較
80>22? Y 80,22,57,60,50
57>80? N 80,22,57,60,50
60>80? N 80,22,57,60,50
50>80? N 80,22,57,60,50
入れ替え結果
80,22,57,60,50

二個目と比較
57>22? Y 80,57,22,60,50
60>57? Y 80,60,22,57,50
50>60? N 80,60,22,57,50
入れ替え結果
80,60,22,57,50

三個目と比較
57>22? Y 80,60,57,22,50
50>57? N 80,60,57,22,50
入れ替え結果
80,60,57,22,50

四個目と比較
50>22? Y 80,60,57,50,22
入れ替え結果
80,60,57,50,22


結果
一番目80
二番目60
三番目57
四番目50
五番目22

投稿日時 - 2018-07-19 23:50:34

お礼

回答ありがとうございます。

投稿日時 - 2018-07-20 12:34:32

こっちだったのね^^
for (int s= 0; s < num - 1; s++)
for (int t = s + 1; t < num; t++)

で、ここのnumは宣言で、5と書いてあります。
const int num = 5;
なので、
for (int s= 0; s < 5 - 1; s++)
for (int t = s + 1; t < 5; t++)
と展開されます。
1つ目のFORループは、5-1なので、4未満
2つ目のFORループはそれに1を足したもの3+1つまり、最大4が入ってます。
なぜ、1つずらすかというと、先ほど書いた
int tmp = test[t];
test[t] = test[s];
test[s] = tmp;
ここに関係します。
t==sだと、同一配列を表すので、別の場所と比較する必要があるからです。
例えば、
if (test[t] > test[s]) {
これの時、t==sだと、
if (test[0] > test[0]) {
と、同じものを比較する無意味なコードを作り出すためです。

投稿日時 - 2018-07-19 23:45:30

お礼

回答ありがとうございます。

投稿日時 - 2018-07-20 12:33:53

バブルソートか。なつかしい!
int tmp = test[t];
test[t] = test[s];
test[s] = tmp;
ここが、わかればほとんど大丈夫かと思います。
test[t] と test[s]の中身が入れ替わる
ってことだけが、一番大きいポイントです。
で、
if (test[t] > test[s]) {
ここが、条件、大きい順や、小さい順にすることを
決めてるのが、ここです。

>22,80,57,60,50の順でお願いします。
別に数字はなんでもOKですよ。
これバブルソートなので、どんな値が来ても、
必ずソートされますので。

投稿日時 - 2018-07-19 22:35:40

お礼

回答ありがとうございます。
正直に申しますと、
for (int s= 0; s < num - 1; s++)
for (int t = s + 1; t < num; t++)
ここの部分がよく解っておりません;
恥ずかしながらご教示お願いします;

投稿日時 - 2018-07-19 22:53:17