目次
ヒルソートとは何ですか?
Hill ソートのコードを記述する前に、Hill ソートのソート原理と定義を整理しましょう。
シェルのソートは縮小増分ソートとも呼ばれ、挿入ソート カテゴリに属する方法ですが、前述のトータル ソート方法よりも時間効率が大幅に向上します。ヒル ソートの基本的な考え方は、まずソート対象のレコードのシーケンス全体をいくつかの単語シーケンスに分割し、それぞれ直接挿入ソートを実行します。次に、シーケンス全体のレコードが「」の場合、すべてのレコードに対して直接挿入ソートを実行します。基本的には順番どおりです。」
ヒルソートは挿入ソートの最適化に相当します.以前の記事C言語での挿入ソートの実装で述べたように, 挿入ソートはシーケンスの一部がすでに順序付けられているソートです.挿入ソートは順序が整っていればいるほど,効率を高める
ヒルソートの使用シナリオ:
ヒル ソートは、中規模のデータ ボリュームのソートに適しています。
ソート間の比較による Hill ソートを導入します。
たとえば、ここではシーケンスが与えられています。
int ar[5] = {1,2,3,4,0};
このときバブルソートを使用すると、要素0が先頭に来るまでの合計実行回数は4回となり、各回の実行順序は次のようになります。
{1,2,3,0,4};
{1,2,0,3,4};
{1,0,2,3,4};
{0,1,2,3,4};
しかし、挿入ソートを使用すると効率が大幅に向上し、要素 0 を先頭に配置できるのは 1 回だけになります。
まず、添字が 0 番目の要素に到達するまで配列をスキャンしますが、後者が前者より大きいという規則を満たさないため、この時点で temp に 0 を代入し、以前にソートされたシーケンスと比較します。小さいほうがよいので、要素 1、2、3 を 1 ビット後ろに移動し、0 を前に置きます。
{0,1,2,3,4};
ヒル ソートに戻りましょう。ヒル ソートは、挿入ソートの最適化と同等です。挿入ソートには、バブル ソートや選択ソートより明らかな利点がありますが、シーケンス内にソートが必要な要素が多数ある場合、毎回毎回隣接する要素と比較するのは少し複雑ですが、ヒル ソートはこの複雑さを解決するように設計されています。
ヒルソートのプロセスをデモンストレーションします。
図に示すように、配列を与えます。
{10,11,13,5,0,13,2,7,8,6,0};
最初のパスを並べ替えます。
次に、製図板上での Hill ソートのプロセスを示します。
2 番目の並べ替え:
並べ替えの増分をシーケンス全体の長さとして定義し、それを直接比較します。10 > 0 であることがわかり、2 つの要素の位置が交換され、次の並べ替えでは並べ替えの増分が元の半分に減ります。
ギャップ値を整数値の形式で定義しているため、要素数は 11 で、11 / 2 は 5.5 です。ここでは、ギャップ値をそのまま 5 として、11 > 2、13 > 7 がわかります。 , 13 > 10, したがって、これら 6 つの要素の位置が入れ替わります。図の下の部分は、2 回目のソート後の要素の順序: 0 2 7 5 0 10 11 13 8 6 13 です。
3 番目の並べ替え:
このとき、ギャップの値は 2 回目の半分になります: 5 / 2 = 2.5。ここではギャップの値は 2 です。
7 > 0、13 > 11 > 8、これら 6 つの要素の位置が交換され、図の下の部分が 3 回目の並べ替え後の要素であることがわかりました: 0 2 0 5 7 6 8 10 11 13 13
4 番目の並べ替え:
このとき、gap の値は 1 となり、直接挿入ソートと同等になります。4 回目のソート結果も最終的なソート結果となります。2 > 0、7 > 6 であることがわかり、これらの位置を入れ替えます。 4 つの要素と並べ替え 最終結果は次のようになります: 0 0 2 5 6 7 8 10 11 13 13
プログラムの検証:
図に示すように、11 個の数値が正常にソートされています。
コード:
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#define MAXSIZE 11
void initar(int *ar,int len)
{
assert(ar != nullptr);
for(int i = 0;i < len;i++){
ar[i] = rand() % 20;
}
}
void showar(int *ar,int len)
{
assert(ar != nullptr);
for(int i = 0;i < len;i++){
printf("%d ",ar[i]);
}
printf("\n--------------------------\n");
}
void Shell_sort(int *ar, int len) {
assert(ar != nullptr && len >= 0);
int i = 0,j = 0;
int temp = 0;//定义中间值用于存储数据
int gap = 0;//定义排序增量
gap = len;//将排序增量的初始值直接设置为数组的长度
while(gap > 1){
gap /= 2;
for(i = gap;i < len;i += gap){
if(ar[i] < ar[i - gap]){
temp = ar[i];
for(j = i - gap;j >= 0 && ar[j] > temp;j -= gap){
ar[j + gap] = ar[j];
}
ar[j + gap] = temp;
}
}
}
}
int main()
{
srand((unsigned int)time(NULL));
int ar[MAXSIZE];
initar(ar,MAXSIZE);
printf("原始数据为:\n");
showar(ar,MAXSIZE);
printf("\n经过希尔排序后的数据为:\n");
Shell_sort(ar,MAXSIZE);
showar(ar,MAXSIZE);
}
コンピュータがランダムに生成した20個以下の12個の数値を使って、並び替えにヒルソートを使ってみましょう 関数のforループの3層目の最後にdisplay array文を追加して、それぞれに配列全体を出力しますソートパスの結果を見てみましょう:
図に示すように、ヒル ソートを使用して合計 4 回 (ギャップの値を 4 回変更する) ソートを実行し、最終的にシステムがランダムに生成したデータの昇順ソートを完了しました。
現実のヒルソーティング:
私たちは皆、ポーカーをプレイしたことがあります。たとえプレイしたことがなくても、他の人がポーカーをプレイしているのを見たことがあるでしょう。ポーカーのデッキは購入するときはすべて新品であり、小さいものから大きいものまでさまざまなスーツに応じて分類されています。ソートプロセス これは単純なヒルソートと考えてください。
54 枚のトランプを小さいものから大きいものまで並べ替える前に、まずトランプをクラブ、ダイヤ、スペード、ハートに対応する異なるスートに従って 4 つのグループに分割する必要があります。そうすれば、現在の並べ替えの増分は次のようになります。 4. 次に、13 個の数字を小さい順から大きい順にソートします (ソート単位は 1、ソート方法は直接挿入ソートです)。
したがって、トランプのソートは単純なヒルソートとみなすことができ、ソートの増分は 4 から 1 に変化し、2 回のパスの後、最終的にソートが完了します。
ヒルソートの概要:
ヒル ソートの時間計算量はソート増分 (ギャップ) に応じて変化します。時間計算量は O(nlogn) ~ O( ) の間で変化し、空間計算量は常にO(1) です。ヒル ソーティングは不安定なアルゴリズムです。
ヒルソートの実行順序は、ソート増分が減少し、増分が 1 になったら直接挿入ソートを実行します。
一時変数のみを保存する必要があるため、空間複雑度は O(1) です。
ヒル ソートは不安定なアルゴリズムです。ソートの増分により、シーケンスは異なるシーケンスに分割されますが、これにより、同じ要素の相対位置が変化する可能性があります。たとえば、奇数のシーケンス {4,5,3,2,1このときのソート増分(ギャップ)の値が2の場合、最後の要素1の相対位置が変わります。