第12講 様々な並び替えの方法 
第6話 並び替え第3の方法
前話で、隣同士を比較して大きい順に並び替えていってそれをN(Nはデータ数)回繰り返したことによる、
並び替えを考えました。
しかし、この方法だとNの2乗回ループを繰り返さなければなりません。
例えば、データ数が100個なら10000回、データ数が100000個なら10000000000回もループを繰り返さなければなりません。
これだとさすがのコンピュータも処理に時間がかかってしまいます。
そこで、第5話の方法の改良を考えたいと思います。
最初にデータを大まかに5分類してから並び替えをするようにさせたいと思います。
まず、最大値と最小値を求めます。
次に、最大値と最小値の差を求めそれを4で割ったものを幅としてそれで分類するのです。
データ数が10個で
41 67 34 0 69 24 78 58 62 64 
である場合を例に説明すると、
最大値が78、最小値が0ですから、
(最大値−最小値)÷4=19.5です。
これを使って次のように分類します。
第1群 78以下で58.5より大きい場合 該当は67,69,78,62,64
第2群 58.5以下で39より大きい場合 該当は41,58
第3群 39以下で19.5より大きい場合 該当は34,24
第4群 19.5以下で0以上の場合  該当は0
最初の分類でデータは
67 69 78 62 64 41 58 34 24 0
となります。
これで前回の並び替え
       void Nb(int* p,int n){
           char i,j;
           int w,cn;
           for(i=0;i<n-1;i++){
             cn=0;
             for(j=0;j<n-1;j++){
               if(p[j]<p[j+1]){
                 w=p[j];
                 p[j]=p[j+1];
                 p[j+1]=w;
                 cn++;
               }
             }
             if(cn==0)break;
           }
           String^ v=L"";
           for(i=0;i<n;i++) v+=(p[i]).ToString()+L"
";
             textBox8->Text=v;
       }
を適用すると、3回のループで終わります。
分類を行わず41 67 34 0 69 24 78 58 62 64 のままで並び替えに掛けると、10回のループになります。
明らかに4分類してから、並び替えをした方が効率がいいことが分かります。
さらに、データ数が大きい場合の実験結果も示しておきましょう
41 67 34 0 69 24 78 58 62 64 5 45 81 27 61 91 95 42 27 36 91 4 2 53 92
82 21 16 18 95 の場合は、
分類しないで並び替えると29ループであるのにたいして7ループです。計算回数は30×29=870回に対して、
分類する場合は分類に要した計算回数も含めて計算して30×(7+4)=330回で、計算回数は約37%で済んでいます。
また、47 26 71 38 69 12 67 99 35 94 3 11 22 33 73 64 41 11 53 68 47 44
62 57 37 59 23 41 29 78 の場合は、
ループ数は28VS5となり、計算回数は840回VS270回で、約3分の1です。
データ数が多いほど、分類した方が有利になります。
例えば、データ数100の
33 15 39 58 4 30 77 6 73 86 21 45 24 72 70 29 77 73 97 12 86 90 61 36 55
67 55 74 31 52 50 50 41 24 66 30 7 91 7 37 57 87 53 83 45 9 9 58 21 88
22 46 6 30 13 68 0 91 62 55 10 59 24 37 48 83 95 41 2 50 91 36 74 20 96
21 48 99 68 84 81 34 53 99 18 38 0 88 27 67 28 93 48 83 7 21 10 17 13 14
の場合、ループ数は87VS22で、計算回数は8700回VS2600回となり、約3.3分の1となります。節約回数は、6100回にも及びます。
プログラム例を示して第6話は閉めたいと思います。
まず、フォームは次のようになっています。

そして、コードは下記の通りです。
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
         int a[N];
         int n=int::Parse(textBox1->Text);
         ds(a,n);
         if(n>9)Br(a,n);
         Nb(a,n);
      }
      void Br(int* p,int n){
         char i,j;
         int w=0;
         int max=0,min=100;
         for(i=0;i<n;i++){
           if(max<p[i])max=p[i];
           if(min>p[i])min=p[i];
         }
         textBox3->Text=max.ToString();
         textBox4->Text=min.ToString();
         double hb;
         hb=((double)max-(double)min)/(double)4;
         char a[4][N];
         char cn[4];
				
         for(i=0;i<4;i++){
           cn[i]=0;
           for(j=0;j<n;j++){
             if(i<3){
               if(p[j]>max-(i+1)*hb && p[j]<=max-i*hb){
                 a[i][cn[i]]=p[j];
                 cn[i]++;
               }
            if(i==3){
               if(p[j]>=max-(i+1)*hb && p[j]<=max-i*hb){
                 a[i][cn[i]]=p[j];
                 cn[i]++;
               }
             }
           }
        }
        char ks=0;
         for(i=0;i<M+1;i++){
           if(cn[i]>0){
             for(j=0;j<cn[i];j++){
               p[ks]=a[i][j];
               ks++;
             }
           }
        } 
    }
    void Nb(int* p,int n){
       char i,j;
       int w,cn;
       for(i=0;i<n-1;i++){
         cn=0;
         for(j=0;j<n-1;j++){
           if(p[j]<p[j+1]){
             w=p[j];
             p[j]=p[j+1];
             p[j+1]=w;
             cn++;
           }
         }
         if(cn==0){
            textBox6->Text=(i+1).ToString();
            break;
         }
       }
       String^ v=L"";
       for(i=0;i<n;i++) v+=(p[i]).ToString()+L" ";
       textBox5->Text=v;
    }
    void ds(int* p,int n){
       int i;
       String^ w=L"";
       for(i=0;i<n;i++){
         p[i]=rand() % 100;
         w+=(p[i]).ToString()+L" ";
       }
       textBox2->Text=w;
    }
(コピーペースト用
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
				 int a[N];
				 int n=int::Parse(textBox1->Text);
				 ds(a,n);
				 if(n>9)Br(a,n);
				 Nb(a,n);
			 }
			 void Br(int* p,int n){
				 char i,j;
				 int w=0;
				 int max=0,min=100;
				 for(i=0;i<n;i++){
					 if(max<p[i])max=p[i];
					 if(min>p[i])min=p[i];
				 }
				 textBox3->Text=max.ToString();
				 textBox4->Text=min.ToString();
				 double hb;
				 hb=((double)max-(double)min)/(double)4;
				 char a[4][N];
				 char cn[4];
				 for(i=0;i<4;i++){
					 cn[i]=0;
					 if(i<3){
						for(j=0;j<n;j++){
							 if(p[j]>max-(i+1)*hb && p[j]<=max-i*hb){
								 a[i][cn[i]]=p[j];
								 cn[i]++;
							 }
						}
					 }
					 if(i==3){
						for(j=0;j<n;j++){
							 if(p[j]>=max-(i+1)*hb && p[j]<=max-i*hb){
								 a[i][cn[i]]=p[j];
								 cn[i]++;
							 }
						}
					 }
				 }
				 char ks=0;
				 if(cn[i]>0){
					 for(i=0;i<4;i++){
						 for(j=0;j<cn[i];j++){
							 p[ks]=a[i][j];
							 ks++;
						 }
					 }
				 }
			 }
			 void Nb(int* p,int n){
				 char i,j;
				 int w,cn;
				 for(i=0;i<n-1;i++){
					 cn=0;
					 for(j=0;j<n-1;j++){
						 if(p[j]<p[j+1]){
							 w=p[j];
							 p[j]=p[j+1];
							 p[j+1]=w;
							 cn++;
						 }
					 }
					 if(cn==0){
						 textBox6->Text=(i+1).ToString();
						 break;
					 }
				 }
				 String^ v=L"";
				 for(i=0;i<n;i++) v+=(p[i]).ToString()+L" ";
					 textBox5->Text=v;
				 }
				 void ds(int* p,int n){
					 int i;
					 String^ w=L"";
					 for(i=0;i<n;i++){
						 p[i]=rand() % 100;
						 w+=(p[i]).ToString()+L" ";
					 }
					 textBox2->Text=w;
				 }
)
かなり難解なプログラムとなっていますので、次回以降詳しく解説いたします。
第11講第6話へ 第12講第5話へ 第12講第7話へ 第13講第1話へ

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