ヒルソートアルゴリズムを理解する

    このチュートリアルでは、ヒルソートがどのように機能するかを学習します。さらに、C言語を使用した例があります。
    ヒルソートは、最初に互いに分離された要素をソートし、次にソートされる要素間の間隔を順番に短縮するアルゴリズムです。挿入ソートの一般的なバージョンです。
    ヒルソートでは、要素は特定の間隔でソートされます。要素間の間隔は、使用順序に応じて徐々に減少します。ヒルソートのパフォーマンスは、特定の入力配列に使用されるシーケンスのタイプによって異なります。
    使用するのに最適なシーケンスのいくつかは次のとおりです。

  • ヒルの元のシーケンス:N / 2、N / 4、…、1
  • クヌースの増分:1、4、13、…、(3k – 1)/ 2
  • セッジウィックの増分:1、8、23、77、281、1073、4193、16577…4j + 1 + 3・2j + 1
  • ヒバードの増分:1、3、7、15、31、63、127、255、511 ..
  • ペーパーノフとスタセビッチの増分:1、3、5、9、17、33、65、..
  • プラット:1、2、3、4、6、9、8、12、18、27、16、24、36、54、81…
ヒルソートはどのように機能しますか?
  1. 次の配列を並べ替える必要があるとします。
    ここに画像の説明を挿入
  2. アルゴリズムでは、Hillの元のシーケンス(N / 2、N / 4、... 1)を間隔として使用します。
    最初のループでは、配列サイズがN = 8の場合、間隔がN / 2 = 4の要素が比較され、交換されます(順序が正しくない場合)。
    a。0番目の要素を4番目の要素と比較します。
    b。0番目の要素が4番目の要素より大きい場合、4番目の要素は最初に一時変数に格納され、0番目の要素(つまり大きい方の要素)は4番目の位置に格納され、tempに格納された要素は格納されます0番目の位置。
    ここに画像の説明を挿入
        残りのすべての要素について、このプロセスは続行されます。
    ここに画像の説明を挿入
  3. 2番目のループでは、N / 4 = 8/4 = 2の間隔を取り、これらの間隔で要素を再度並べ替えます。
    ここに画像の説明を挿入
        この時点で混乱するかもしれません。
    ここに画像の説明を挿入
        4番目と2番目の要素が比較され、2番目と0番目の要素も比較されます。配列内の現在の間隔のすべての要素が比較されます。
  4. 同じプロセスが残りの要素に適用されます。
    ここに画像の説明を挿入
  5. 最後に、間隔がN / 8 = 8/8 = 1の場合、間隔が1の配列要素がソートされます。これで配列がソートされました。
    ここに画像の説明を挿入

注:
元のテキストの2回目の並べ替えの凡例は正しくありません。
最初の間隔は4で、並べ替え後の配列は次のとおりです。

5 6 3 1 9 8 4 7

正しい。
2番目の間隔は2で、それぞれ5,3,9,4と3,4,5,9を並べ替えます。並べ替え後の配列は、次のとおりです。

3 1 4 6 5 7 9 8

3番目の間隔は1で、並べ替え後の配列は次のとおりです。

1 3 4 5 6 7 8 9
ヒルソートアルゴリズムの擬似コード
shellSort(array, size)
  for interval i <- size/2n down to 1
    for each interval "i" in array
        sort all the elements at interval "i"
end shellSort
Cの例
// Shell Sort in C programming

#include <stdio.h>

// Shell sort
void shellSort(int array[], int n) {
    
    
  // Rearrange elements at each n/2, n/4, n/8, ... intervals
  for (int interval = n / 2; interval > 0; interval /= 2) {
    
    
    for (int i = interval; i < n; i += 1) {
    
    
      int temp = array[i];
      int j;
      for (j = i; j >= interval && array[j - interval] > temp; j -= interval) {
    
    
        array[j] = array[j - interval];
      }
      array[j] = temp;
    }
  }
}

// Print an array
void printArray(int array[], int size) {
    
    
  for (int i = 0; i < size; ++i) {
    
    
    printf("%d  ", array[i]);
  }
  printf("\n");
}

// Driver code
int main() {
    
    
  int data[] = {
    
    9, 8, 3, 7, 5, 6, 4, 1};
  int size = sizeof(data) / sizeof(data[0]);
  shellSort(data, size);
  printf("Sorted array: \n");
  printArray(data, size);
}
複雑さ

    ヒルソートは、アルゴリズムが間隔間で要素をチェックしないため、不安定なソートアルゴリズムです。
    時間の複雑さ

  • 最悪の場合の複雑さ:O(n 2 n ^ 2以下)n2
        Poonenの定理によると、ヒルソートの最悪の場合の複雑さはΘ(N log N)2 /(loglog N)2)Θ(NlogN)^ 2 /(log log N)^ 2)です。Θ N l o g N 2 /loglogN2またはΘ(N log N)2 / loglog N)Θ(NlogN)^ 2 / log log N)Θ N l o g N 2 /loglogNまたはΘ(N(log N)2)Θ(N(log N)^ 2)Θ N l o g N 2またはその間のどこか。
  • 最良の場合の複雑さ:O(n * log n)
        配列がソートされると、各間隔(または増分)の比較の総数は配列のサイズに等しくなります。
  • 平均的なケースの複雑さ:O(n * log n)は
        約O(n 1.25)O(n ^ {1.25})O n1 2 5

    複雑さは、選択した間隔によって異なります。選択された増分シーケンスが異なると、上記の複雑さが異なります。最適な増分シーケンスは不明です。
    スペースの複雑さ:ヒルソートのスペースの複雑さ
    はO(1)です。

ヒルソートアプリケーション

    次の状況でヒルソートを使用します。

  • コールスタックは毎日のオーバーヘッドです。uClibcライブラリはこの並べ替えを使用します。
  • 再帰が制限を超えています。bzip2コンプレッサーはそれを使用します。
  • 隣接する要素が離れている場合、挿入ソートのパフォーマンスは良くありません。ヒルソーティングは、隣接する要素間の距離を短くするのに役立ちます。したがって、実行する交換の数は少なくなります。
参考文献

[1] ParewaLabsPvt。Ltd.ShellSortAlgorithm [EB / OL] .https://www.programiz.com/dsa/shell-sort,2020-01-01。
[2] Baidu。HillSort [EB / OL] .https://baike.baidu.com/item/Hillsorting、2020-11-18。

おすすめ

転載: blog.csdn.net/zsx0728/article/details/115040643