何気なく始めた【ソート】シリーズBubble SortHeap SortQuick Sortと進めましたが、今回がアルゴリズム紹介の最後で「シェルソート(Shell Sort)」をやります。(今回も詳しく調べられる方の為にwikiの参照を載せます。)

 

”Shell”というのが最初「貝」を連想させましたが、全く関係なくて、アルゴリズムを開発した方の名前なんですね。アルゴリズムは「(一定の距離をおいた)飛び飛びの列を(距離を縮めながら)繰り返しソートして、配列を大まかに整列された状態に近づけていく」(↑のwiki記事参照)というものです。

 

ではコードを見てゆきます。

 

//////////////
// Shell Sort
//////////////
//シェルソートは配列要素を一定の距離を置いたグループに分けて比較、交換を行いソートする方法

void shellsort(int *v, int n) {

    int gap, i, j, temp;    //gapは比較、交換する要素間の距離

    for(gap = n / 2; gap > 0; gap /= 2) {    //初期的な距離は配列サイズの1/2とする
        for(i = gap; i < n; i++) {            //距離は徐々に狭まってゆく
            for(j = i - gap; j >= 0 && v[j] > v[j + gap]; j -= gap) {
                //v[j]とv[j + gap]を交換する(解説:if文が無いのはforの条件に反映しているから)
                temp = v[j];
                v[j] = v[j + gap];
                v[j + gap] = temp;
            }
        }
    }
 

今回も実際に処理の動きを見て行きましょう。

 

配列 = {2, 7, 3, 5, 8, 0, 6, 1, 4};
要素数 9


1.3つのforループ

解説:距離(gap)を要素数の半分(4)にし、第2のforループでgapから末尾迄進め、第3のforループでgap間の2要素を比較、交換する。

配列 = {2, 7, 3, 5, 8, 0, 6, 1, 4};
           ↑          ↑
           比較対象 >  gap  →  交換
配列 = {2, 0, 3, 5, 8, 7, 6, 1, 4};
 

配列 = {2, 0, 3, 5, 8, 7, 6, 1, 4};
                 ↑          ↑
                 比較対象 >  gap  →  交換
配列 = {2, 0, 3, 1, 8, 7, 6, 5, 4};
 

配列 = {2, 0, 3, 1, 8, 7, 6, 5, 4};    //第3のループ2回目
                        ↑          ↑
                        比較対象 >  gap  →  交換なし
配列 = {2, 0, 3, 1, 4, 7, 6, 5, 8};    //第3のループ2回目

解説:第2ループのカウンターiがnになったので第2ループを抜ける。

2.再度3つのforループ

解説:第1のループで距離(gap)を半分(2)にし、同様に第2、第3のforループでgap間の2要素を比較、交換する。

配列 = {2, 0, 3, 1, 4, 7, 6, 5, 8};
                       ↑    ↑
                    比較対象>gap  →  交換
配列 = {2, 0, 3, 1, 4, 5, 6, 7, 8};

解説:第2ループのカウンターiがnになったので第2ループを抜ける。

3.再々度3つのforループ

解説:第1のループで距離(gap)を半分(1)にし、同様に第2、第3のforループでgap間の2要素を比較、交換する。

配列 = {2, 0, 3, 1, 4, 5, 6, 7, 8};
        ↑ ↑
        | gap
      比較対象 →  交換
配列 = {0, 2, 3, 1, 4, 5, 6, 7, 8};
 

配列 = {0, 2, 3, 1, 4, 5, 6, 7, 8};
              ↑ ↑
              | gap
            比較対象 →  交換
配列 = {0, 2, 1, 3, 4, 5, 6, 7, 8}; 
 

配列 = {0, 2, 1, 3, 4, 5, 6, 7, 8}; 
           ↑ ↑
           | gap
         比較対象 →  交換
配列 = {0, 1, 2, 3, 4, 5, 6, 7, 8}; 
 

如何でしたでしょうか?あっさりとソートされた、という感じですかね?

これで主たるソートアルゴリズムの紹介を終えますが、(ドラゴンボールみたいに)【ソート】シリーズはもうちょっと続きます。

 

【ご参考】(解説:↑の例のshellsortソート実行中の配列変化の出力)

>>> オリジナルデータ <<<
     2,      7,      3,      5,      8,      0,      6,      1,      4


>>> Shell Sort started ... <<<
>>> 第0回目の交換 <<<
     2,      
0,      3,      5,      8,      7,      6,      1,      4
>>> 第1回目の交換 <<<
     2,      0,      3,      
1,      8,      7,      6,      5,      4
>>> 第2回目の交換 <<<
     2,      0,      3,      1,      
4,      7,      6,      5,      8
>>> 第3回目の交換 <<<
     2,      0,      3,      1,      4,      
5,      6,      7,      8
>>> 第4回目の交換 <<<
     
0,      2,      3,      1,      4,      5,      6,      7,      8
>>> 第5回目の交換 <<<
     0,      2,      
1,      3,      4,      5,      6,      7,      8
>>> 第6回目の交換 <<<
     0,      
1,      2,      3,      4,      5,      6,      7,      8

>>> Shell Sort completed! <<<
     0,      1,      2,      3,      4,      5,      6,      7,      8


Push CR key ...