C# はヒル ソートを実装します
プロセス解体
次のように、既存の配列があるとします。
基本的な並べ替えコードは次のとおりです。
static void Main(string[] args)
{
int[] array = new int[] {
5, 4, 5, 2, 3, 6, 1 };//替换代码
BaseSort(array, 3);//替换代码
for (int i = 0; i < array.Length; i++)
{
Console.Write(array[i] + " ");
}
Console.ReadKey();
}
public static void BaseSort(int[] array, int gap)
{
for (int i = gap; i < array.Length; i++)
{
int insertValue = array[i];
for (int j = i - gap; j >= 0; j -= gap)
{
if (insertValue < array[j])
{
array[j + gap] = array[j];
array[j] = insertValue;
}
else
{
break;
}
}
}
}
- 置換コードを次のコードに置き換え、実行して分析します
int[] array = new int[] {
5, 4, 5, 2, 3, 6, 1 };
BaseSort(array, 3);
//将下标差值为 3 的一组数进行排序
添字3 で前方に 3 の間隔で数添字0 を見つけ、挿入ソート アルゴリズムを使用してソートします。
subscript 4 forwardで間隔が 3 の数subscript 1 を見つけ、挿入ソート アルゴリズムを使用してソートします。添字 5で前方に 3 の間隔で数添字2 を見つけ、挿入ソート アルゴリズムを使用してソートします。添字 6 前方に3 間隔で数添字3と添字 0を見つけ、このとき添字 0 と添字 3 がソートされていることを確認し、挿入ソート アルゴリズムを使用してソートします。
- 置換コードを次のコードに置き換え、実行して分析します
int[] array = new int[] {
1, 3, 5, 2, 4, 6, 5 };
BaseSort(array, 1);
//将下标差值为 1 的一组数进行排序
添え字1 から1 間隔で数添え字0 を見つけ、挿入ソート アルゴリズムを実行して並べ替えます。添字 1 から 1間隔で数添字1 と添字 0 を求め、ソートには挿入ソートアルゴリズムを実行します。添字1 前方、添字 2、添字 1、添字 0 で間隔 1 の数を求め、ソートには挿入ソート アルゴリズムを実行します。添字 1前方、添字 3、添字 2、添字 1、添字 0 の間隔が 1 の数を見つけ、ソートには挿入ソート アルゴリズムを実行します。添字 1前方、添字 4、添字 3、添字 2、添字 1、添字 0の間隔が 1のを見つけ、ソートには挿入ソート アルゴリズムを実行します。添字1 前方、添字 5、添字 4、添字 3、添字 2、添字 1、添字 0の間隔が 1のを求め、ソートには挿入ソート アルゴリズムを実行します。
アルゴリズムの実装
- ヒル ソートは、グループソートに間隔を使用し、直接挿入ソート アルゴリズムを最適化します。
- 配列の長さの半分を初期間隔の長さとして選択し、それらを並べ替えます。その後、ループは間隔としてn/2を取ります。
- 可能な限り、最後の直接挿入ソートの時間アルゴリズムの複雑さを O(n) とします。
コードは以下のように表示されます
static void Main(string[] args)
{
int[] array = new int[] {
5, 4, 5, 2, 3, 6, 1 };
ShellSort(array);
for (int i = 0; i < array.Length; i++)
{
Console.Write(array[i] + " ");
}
Console.ReadKey();
}
public static void ShellSort(int[] array)
{
for (int gap = array.Length / 2; gap > 0; gap /= 2)
{
//直接插入排序算法
for (int i = gap; i < array.Length; i++)
{
int insertValue = array[i];
for (int j = i - gap; j >= 0; j -= gap)
{
if (insertValue < array[j])
{
array[j + gap] = array[j];
array[j] = insertValue;
}
else
{
break;
}
}
}
}
}
分割コードは以下の通り
public static void ShellSort(int[] array)
{
for (int gap = array.Length / 2; gap > 0; gap /= 2)
{
InsertSort(array, gap);
}
}
public static void InsertSort(int[] array, int gap)
{
for (int i = gap; i < array.Length; i++)
{
int insertValue = array[i];
for (int j = i - gap; j >= 0; j -= gap)
{
if (insertValue < array[j])
{
array[j + gap] = array[j];
array[j] = insertValue;
}
else
{
break;
}
}
}
}
複雑さと安定性
- 最適な時間の複雑さ:間隔が 1 で順序が並べ替えられている場合、挿入並べ替えの最初の for ループのみを経験する必要があります。
- 最悪の時間の複雑さ: 配列が逆順の場合、挿入ソートの 2 番目の for ループの実行回数は、Hill ソートの間隔演算の後に減らすことができます。したがって、実際のソート時間は、直接挿入ソートの最悪の時間の複雑さと同じです。
- 平均時間の複雑さ: 主に間隔の値に依存します
- スペースの複雑さ: insertValue 変数を使用して、比較のために値を記録する必要があります
- 安定性: ソートアルゴリズムの後、以前の値は後ろにランク付けされます (例: 5)
著者のエネルギーが限られているため、記事には間違いや脱落が避けられませんが、専門家やネチズンは私を批判して修正することを歓迎します。