6.5 シェルソート

番号 以下をクリックすると,該当箇所にジャンプします
(1) シェルソートとは
(2) 増分の選択

(1)シェルソートとは


単純挿入法によるソートは,単純交換法,単純選択法と同様,
計算量はO(N2)です。

一方,単純挿入法には,以下の特徴があります。

(a) ソート済み,またはそれに近いとき高速である。
(b) 挿入先が離れているとき,ずらす回数が多くなる。

最初,なるべく離れた要素をグループ化して,
大まかなソートを行い,そのグループを縮めていくことで,

(a)の長所を活かし,(b)の短所を補うことができます。
この方法をシェルソートと呼びます。

まず,以下の例を単純挿入法でソートすると,
要素をずらす回数は,14回になります。

    

ここで,まず4つずつ離れたグループ

     {9,8},{2,7},{5,4},{3,7}

でソートすることを考えます。すると,次のようになります。

     

このソートを4−ソートと呼びます。

次に2つずつ離れたグループ

     {8,4,9,5},{2,3,7,6}

内でソート(2−ソート)します。

     

最後に,通常の単純挿入法でソートしてみます。

    

ずらす回数は,最初の単純な14回から6回に減っています。

[プログラム例]

  private void シェルソート()
  {
    int i,j,h, Tmp;
    for(h = Data.Length / 2 ; h > 0; h /= 2)
       for(i = h; i < Data.Length; i++)
       {
        Tmp=Data[i];
        for(j = i - h ; j >= 0 && Data[j] > Tmp; j -= h)
             Data[j + h]=Data[j];
         Data[j + h]=Tmp;
       }
  }


番号 以下をクリックすると,該当箇所にジャンプします
(1) シェルソートとは
(2) 増分の選択

(2)増分の選択


前の例では,等増分を4,2,1と変化させましたが,
以下のように,4−ソートの2グループをあわせたものが,
2−ソートのグループになってしまっています。

     

しかし,各段階のソートでなるべくかき混ぜるほうが,
各段階のソート結果を反映することになりますので,
効率よくなるはずです。

このためには,増分がお互いの倍数にならないようにします。
たとえば,次のようにします。

  増分=1, 4, 13, 40, 121 (1から始めて3倍して1を加える)

ただし,増分が大きすぎても効果がないことが知られていますから,
最大増分量は,配列の要素数/9を超えないようにします。

このようにして改良した方法が,以下のプログラム例です。

[プログラム例]

  private void シェルソート改良版()
  {
    int i, j, h, Tmp;
    for(h = 1; h < Data.Length / 9; h = h * 3 + 1);
    for( ; h>0; h /= 3)
      for(i = h; i < Data.Length; i++)
      {
        Tmp = Data[i];
        for(j = i - h ; j >= 0 && Data[j] > Tmp; j -= h)
           Data[j + h] = Data[j]; Data[j + h]=Tmp;
       }
  }


番号 以下をクリックすると,該当箇所にジャンプします
(1) シェルソートとは
(2) 増分の選択


1. 基本的なアルゴリズム

2. 基本的なデータ構造

3. 操作を伴うデータ構造

4. 探索

5. 再帰的アルゴリズム

6. ソート

7. 集合

8. 文字列処理

9. 色々なアルゴリズム


上のタイトルをクリックします