第12講 並び替えの方法その1
第6話 隣項交換繰り返し法のエンジン部分解説
並び替えプログラムのエンジン
  public static int h(int x[],int n){
    int i,j,a,v,w;
    for(i=0;i<n;i++){
      v=0;
      for(j=0;j<n-1;j++){
        if(x[j]<x[j+1]){
          w=x[j];
          x[j]=x[j+1];
          x[j+1]=w;
          v++;
        }
      }
      if(v==0)break;
    }
    return(i);
  }
解説
さて、隣項交換繰り返し法の核部分を解説しましょう。

8,6,10,4,9の並び替えの交換されいく過程を見ながら、コードを読んでください。

8,6,10,4,9
8,6,10,4,9
8,10,6,4,9
8,
10,6,4,9
8,10,
6,4,9
8,10,6,9,4
これで一巡しました。
再度同じことを繰り返します。
8,10,6,
9,4
10,8,6,9,4
10,8,6,9,4
10,
8,6,9,4
10,8,
9,6,4
10,8,
9,6,4
2巡目で降順に並び替えるのに成功しました。

次の場合どうでしょうか。
4,9,3,8,10
動きを追ってみましょう。
4,9,3,8,10
9,4,3,8,10
9,4,3,8,10
9,4,3,8,10
9,4,8,3,10
9,4,
8,3,10
9,4,8,10,3
1巡目が終わりです。
9,4,8,
10,3
9,4,8,10,3
9,8,4,10,3
9,
8,4,10,3
9,8,10,4,3
9,8,
10,4,3
2巡目が終了しましたが、まだ降順になっていません。
3巡目に入ります。
9,8,10,
4,3
9,8,10,4,3
9,10,8,4,3
9,
10,8,4,3
9,10,
8,4,3
3巡目終了時にもまだ、降順になっていません。
9,10,8
,4,3
10,9,8,4,3
10,9,8,4,3
10,9,8,4,3
10,9,8,4,3
4巡目で降順に並び替えるのに成功しました。

本当は
    for(i=0;i<n;i++){
        ・
        ・
    }
はwhile文で行った方がよいわけです。
というのはループが何巡目に終了するかがわかっていないからです。
終了回数がわからないときは、while文を使うのです。
ですが、皆さんはまだwhile文を学んでいないので、
先の仮説『nこのデータならn巡以内に並び替えに成功する』に基づいてfor文で組んでみました。
仮説が正しくない場合、このfor文プログラムではアウトになりますが、
幸いなことに今まで、何万回も実験してきましたが、
『nこのデータならn巡以内に並び替えに成功する』という仮説の反例は見つかっていませんので、
仮説は正しいと考えて良さそうです。


2重ループの役割を確認しましょう。
    for(i=0;i<n;i++){
        ・
    }
は何巡目であるかを示しています。
      for(j=0;j<n-1;j++){
        if(x[j]<x[j+1]){
          w=x[j];
          x[j]=x[j+1];
          x[j+1]=w;
          v++;
        }
      }
はi+1巡目においてすべての隣項を比較して、右の方が大きいときに交換しています。
j<n-1ですから、一番最後の比較は
        if(x[n-2]<x[n-1])
です。配列は添え字0から始まりますので、n項目はn-1でしたね。
さて、vの役割は何でしょうか。
vは隣項の交換の回数を調べています。
すべての隣項について調べ、すべて左の方が大きいとき交換は1回も行われません。
ですからvが0であったときすでに並び替えが終わっていること意味します。
それで強制的に
      if(v==0)break;
でiのループを終了させています。


さて、これで解説は終わりにします。
さて、課題を出して今話を閉じましょう。
今回
   for(i=0;i<n;i++){
      v=0;
      for(j=0;j<n-1;j++){
        if(x[j]<x[j+1]){
          w=x[j];
          x[j]=x[j+1];
          x[j+1]=w;
          v++;
        }
      }
      if(v==0)break;
    }
をループ(for文)文で処理しましたが、
関数の再帰的呼び出しでもできます。
考えてみましょう。



第5話へ
 第7話へ

戻る

VB講義へ
VB講義基礎へ
vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座

初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部