目次
1. 一般的な並べ替えアルゴリズム
1.1 挿入ソートの基本的な考え方
直接挿入ソートは単純な挿入ソート方法です。その基本的な考え方は、
キー値のサイズに従ってソートされたシーケンスに、ソート対象のレコードを 1 つずつ挿入し、すべてのレコードが挿入されるまで続きます
。順序付けられたシーケンスが得られます。
実際にポーカーをプレイするときは、挿入ソートの考え方を使用します。
2. ヒルソート
2.1 ヒルソート(縮小増分ソート)
ヒル ソート法は、縮小増分法としても知られています。Hill ソート法の基本的な考え方は、まず整数ギャップを選択し、ソートするファイル内のすべてのレコードを複数のグループに分割し、ギャップの距離差があるすべてのレコードを同じグループにグループ化し、ソートを実行します。 。次に、gap=gap/3+1 として、上記のグループ化と並べ替えの作業を繰り返します。ギャップ = 1 に達すると、すべてのレコードが同じグループにソートされます。
分析するための絵を描いてみましょう:私たちは昇順でここにいます
この図から、最後のギャップ = 1 の場合、本質は挿入ソートであり、ヒル ソートは最初に事前ソートを行い、最後にソートを実現するために 1 回ソートを挿入することであることが実際にわかります。
上の図を分析してみましょう。
2.1.1 選別前の段階
1. 最初のトリップで、ギャップ = 5 の場合、次の場合、5 つの数字の間隔ごとにグループが形成され、9 と 4、1 と 8、2 と 6、5 と 3、7 と 5 がグループを形成することを意味します。番号が前の番号より小さい場合は、グループ内の小さい番号を前に、大きい番号を後ろに配置するように交換します。
2. 2 番目のトリップでは、gap = gap/3+1 とします (ここで、gap/3+1 は最終的に gap=1 を取得することです。gap<3 の場合、単純に 3 で割ると 0 が得られるため、完了します)ソートはできません)、gap=2、2 つの数字の間隔ごとにグループ、4 は 2、5、8、5 のグループ、1 は 3、9、6、7 のグループ、サイズを比較、次に交換します。
2.1.2 挿入ソートフェーズ
3. ギャップ = 1 を調整する場合、本質は挿入ソートです。この時点では、前のソート前段階を経て、数値は順序に近くなりますが、完全に順序は整っていません。このときの挿入ソートは効率を大幅に向上させます。
2.2 One-way Hill ソート
2.2.1 アイデア分析
シングルパス ヒル ソートは実際には、ギャップで区切られた数値をグループに分割し、最初にソートします。
図面分析:
1 回の旅行の間隔ごとにギャップのある数値をグループに分け、最初に並べ替えます。
2.2.2 コードの実装
for (int i = 0; i < n - gap; i++)//多组一起排序(没有提升效率,只是少写一组循环)
{
int end = i;
int tmp = a[i + gap];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
3. ヒルソートコードの実装
シングルパスソートにループの層を追加し、ギャップが 1 になるまで継続的に減少させ、ヒルソートを実現します。
void ShellSort(int* a, int n)
{
//1. 当 gap > 1 时先进性预排序
//2. 当 gap == 1 时直接插入排序
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;// +1可以保证最后一次一定是1
for (int i = 0; i < n - gap; i++)//多组一块进行
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
4. ヒルソート時間の複雑さ
ヒル ソートの時間計算量は、ギャップを評価する方法が多数あり、計算が困難であるため、計算が容易ではありません。そのため、多くの書籍で示されているヒル ソートの時間計算量は固定されていません。
ヒル ソートの時間計算量について説明した 2 冊の本を次に示します。
ここでのギャップは、Knuth が提案した方法に従って計算されており、Knuth は数多くの実験統計を行っていますが、当面は O(n^1.25) ~ O(1.6*n^1.25) に従って計算します。 。
5. ヒルソートとインサートソートの効率比較
どちらもサイズが 100,000 の 2 つの配列を開き、Hill ソートと挿入ソートを使用して、消費時間を比較します。
//时间对比
void TestOp()
{
srand((unsigned int)time(NULL));
const int n = 100000;
int* a1 = (int*)malloc(sizeof(int) * n);
int* a2 = (int*)malloc(sizeof(int) * n);
for (int i = 0; i < n; ++i)
{
a1[i] = rand();
a2[i] = a1[i];
}
int begin1 = clock();
InsertSort(a1, n);
int end1 = clock();
int begin2 = clock();
ShellSort(a2, n);
int end2 = clock();
printf("InsertSort:%d\n", end1 - begin1);
printf("ShellSort:%d\n", end2 - begin2);
free(a1);
free(a2);
}
int main()
{
TestOp();
return 0;
}
ヒル ソートは挿入ソートよりもはるかに効率的であり、データ量が大きい場合はヒル ソートの方が優勢であることがわかります。
ただし、配列自体が順序付けされている場合、ヒル ソートには事前ソートがあり、実行に時間がかかるため、ヒル ソートは挿入ソートほど優れていません。
6. ヒルソート特性の概要
1. ヒル ソートは直接挿入ソートを最適化したものです。
2. ギャップ > 1 の場合、事前にソートされます。目的は、配列を順序に近づけることです。ギャップ == 1 の場合、配列はすでに順序に近いため、非常に高速になります。これにより、全体の最適化効果が得られる。実装した後は、パフォーマンス テストを比較できます。
3. ヒル ソートの時間計算量は、ギャップを評価する方法が多数あり、計算が困難であるため、計算が容易ではないため、多くの書籍で示されているヒル ソートの時間計算量は固定されていません。4. 安定性:不安定です。