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

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

解決済みの質問

選択ソートについて

-------------------------------------
#include<stdio.h>
int main(void)
{
int min,s,t,i,j;
int num[]={5,6,4,9,2};

for(i=0;i<4;i++){
min=num[i];
s=i;        ////◎1
for(j=i+1;j<5;j++){
if(num[j]<min){
min=num[j];
s=j;
}
}
t=num[i];
num[i]=num[s];
num[s]=t;
}

for(i=0;i<5;i++){
printf("%d ",num[i]);
}

putchar('\n');

return 0;
}
--------------------------------------

以上のプログラムで◎1の記述が無くても正常にソートしてくれたので疑問に思いました。
「s=i;」が無い場合、最初のループのif文で、
if(num[j]<min){
min=num[j];
s=j;
}
「6<5」を比べる時、条件に見合わないので、sに何も代入されず、
t=num[i];
num[i]=num[s];
num[s]=t;
以上の記述で、sが初期化されてないので、その時点のエラーが出ると思ったんですが、出ないで正常に動きました。
何故なのか教えてもらえると嬉しいです。

投稿日時 - 2009-02-17 09:20:58

QNo.4724695

困ってます

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

>以上の記述で、sが初期化されてないので、その時点のエラーが出ると思ったんですが、出ないで正常に動きました。

「◎1の行が無い場合に、sに値が一度も代入されず、不定になる」のは「元々、データがソート済みの時」だけです。

「元々、データがソート済みの時」と言うのは、言い換えれば
if(num[j]<min){
min=num[j];
s=j;
}
の部分を1度も通らない時、です。

◎1が存在する理由は「元々、データがソート済みの時、
if(num[j]<min){
min=num[j];
s=j;
}
の部分を1度も通らないから
t=num[i];
num[i]=num[s];
num[s]=t;
を行っても、入れ替えをしないようにする為」です。

最初に
s=i;
とやっておけば、元々ソート済みの場合
t=num[i];
num[i]=num[s];
num[s]=t;
の所に来た時にsとiが同じ値になっているので、入れ替えは起きません。

以下蛇足。

ANo.3の回答者さんへ

>☆コーディングでは、「インデント」すべきです。

当サイトでは、質問文中、回答文中の「行頭の半角スペース」は、自動的にすべてカットされてしまいます。

なので、質問者さんが「インデント済みの、ちゃんとしたコーディングをしたソースコード」を質問文に貼り付けても、すべてのインデントが勝手に削除されてしまいます。

従って、質問者さん(や他の回答者さん)に対して「ソースコードをインデントしてない」と言う指摘をするのは正当でない可能性があります。

「当サイトでは、インデントは勝手に消えてしまう」と言うのを念頭に置いて、今後、C/C++などのカテゴリで回答する際は「インデントすべき」と言う指摘はしない方が良いです。

下手に指摘すると「いちいちウルサイな。こっちはちゃんとインデントしてあるのを貼ってる。勝手にインデント消えるんだから仕方ないだろ」と思われてしまい、相手に悪い印象を与えます。ご注意を。

投稿日時 - 2009-02-17 12:08:11

お礼

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

>「◎1の行が無い場合に、sに値が一度も代入されず、不定になる」の>は「元々、データがソート済みの時」だけです。
if文の条件が1度も適合しないという事で、上記の内容理解できました。ありがとうございます。

投稿日時 - 2009-02-17 12:36:16

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

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

回答(5)

ANo.5

No.3 です。

>2個目のfor文が範囲の分だけ繰り返し終わってから、
>t=num[i];
>num[i]=num[s];
>num[s]=t;
>以上に進むという感じですよね?

 はい、そうです。
 「 for 構文がどこまでか」が判った、ということですね。
 (構文中で、break; を用い、ループ途中で抜け出すことも可能です)

>初心者なもので、すいません。

 いえいえ、コーディングスタイル(インデント)云々より、「 for 構文の理解」でしたね。
 後先となって、失礼しました。

 今後は、コーディング時に適切にインデントしておけば、視覚的に把握できるかと・・。

No.4 さんへ

>当サイトでは、質問文中、回答文中の「行頭の半角スペース」は、自動的にすべてカットされてしまいます。

 存じていました(このため No.3 回答文中では、全角空白を用いています)。
 連続する複数の半角スペースが1つになること、タブも・・。

>下手に指摘すると「いちいちウルサイな。こっちはちゃんとインデントしてあるのを貼ってる。勝手にインデント消えるんだから仕方ないだろ」と思われてしまい、相手に悪い印象を与えます。ご注意を。

 上手にアドバイスしたい、と思っているのですがなかなか・・、ご注意ありがとうございます。

投稿日時 - 2009-02-17 15:06:00

お礼

最初からソートされていた場合、sに値が代入されず動作が不安定になるという事も理解していなかったのですが、ご指摘通りfor文が多重になった場合の事が、完全に理解できてなかったです。
その後勉強し理解できました。ありがとうございます。

投稿日時 - 2009-02-18 03:20:19

ANo.3

>以上の記述で、s が初期化されてないので、その時点のエラーが出ると思ったんですが、出ないで正常に動きました。

 いいえ、5より小さい4が現れた時点で、s に 2 が代入(「初期化」)されます。
 そしてさらに、2で、s に 4 が代入されます。
 
 最後の2まで比較してから、質問者様の言われる「その時点」に進みます。

先頭データが5でなく、1ですと質問者様期待どおりの結果となります(◆)。
+++++++++++++++++++++++++++++++++++++++++++++++
☆コーディングでは、「インデント」すべきです。

始めから下のようにコーディングしていたら、今回の質問はなかったのではないでしょうか。

  for( i = 0; i < 4; i++ ){

    min = num[ i ];

    s = i; // このステップがない場合(◆)

    for( j = ( i + 1 ); j < 5; j++ ){

      if( num[ j ] < min ){

        min = num[ j ];
        s = j;
      }
    }
    t = num[ i ];
    num[ i ] = num[ s ];  // 「その時点」
    num[ s ] = t;
  }

投稿日時 - 2009-02-17 11:17:24

お礼

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

2個目のfor文が範囲の分だけ繰り返し終わってから、
t=num[i];
num[i]=num[s];
num[s]=t;
以上に進むという感じですよね?

確かに、先頭を「1」にすると、i=0の時、if文の条件が1度も適合せず実行は出来ましたが、エラーを報告する、しないの画面が出てしまいました。

初心者なもので、すいません。

投稿日時 - 2009-02-17 12:19:50

ANo.2

>if(num[j]<min){
>min=num[j];
>s=j;
>}

上記の処理がfor文によるループの中に書いてあって、
1度だけ実行するわけではない(6<5の判定だけではない)ことに留意してください。

投稿日時 - 2009-02-17 10:43:15

お礼

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

まずi=0の時、
for(j=i+1;j<5;j++){
if(num[j]<min){
min=num[j];
s=j;
}
上記を4回繰り返してから、以下を1回実行するという感じですかね?
t=num[i];
num[i]=num[s];
num[s]=t;

初心者なもので、すいません。

投稿日時 - 2009-02-17 12:03:35

ANo.1

int num[]={5,6,7,8,9};
のように最初からソートされている場合のみ s=j;が実行されません。
そして s=i; が無いとsに値が代入されなくなり動作が変になるでしょう。

投稿日時 - 2009-02-17 10:17:50

お礼

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

>最初からソートされている場合のみ s=j;が実行されません。

上記の内容納得出来ました。if文の条件に1度も合わないので、その結果動作が変になってしまうと分かりました。ありがとうございます。

投稿日時 - 2009-02-18 03:06:04

あなたにオススメの質問