出典
ヒルソートを説明する前に、まずヒルソートの起源を理解しましょう。実際、Hillソートは挿入ソートでもあります。これは、Great God Hillによって発明され、単純挿入ソート用に最適化された高度な挿入ソートです。つまり、ヒルソートは挿入ソートでもあります。単純なソートの問題を理解しましょう。
単純挿入ソートの問題
単純な挿入ソートで起こり得る問題を見てみましょう。
配列arr = {2,3,4,5,6,1}現時点では、挿入される数1(最小)です。そのようなプロセスは
、{2,3,4、 5,6,6}
{2,3,4,5,5,6}
{2,3,4,4,5,6}
{2,3,3,4,5,6}
{2,2、 3,4,5,6}
{1,2,3,4,5,6}
結論:挿入される数が少ない場合、バックシフトの数が大幅に増加し、効率に影響します。
ヒルソーティングの基本的な考え方
ヒルソートはどのように最適化されますか?つまり、少数の逆方向シフトの後で、挿入ソートの小さい数を適切な位置に移動させる方法です。
プロの説明をご覧ください:
ヒルソートとは、特定の添え字の増分でレコードをグループ化し、直接挿入ソートアルゴリズムを使用して各グループをソートすることです。増分が徐々に減少すると、各グループに含まれるキーワードが増えます。増分が1に減少すると、ファイル全体がグループに分割され、アルゴリズムが終了します
あなたがそれを理解できるなら、あなたは素晴らしいです。とにかく、理解できませんでした。このアルゴリズムを理解するのに役立つアルゴリズムの画像をいくつか示します。
簡単に言うと、Hillソートにギャップと呼ばれるものが追加され、その初期サイズは配列の長さの半分に等しく、サイクルごとに半分になります。その役割は、配列をグループ化し、配列要素を2つにグループ化し、挿入ソートを実行することです。これにより、ソート操作をできるだけ少ない移動で完了することができます。
具体的な実現
その後、特定のコード実装に到達します。
配列arr [8,9,1,7,2,3,5,4,6,0]、Hillをソートするとします。上記の知識によると。
- 最初に、増分が0より大きいかどうかを判断します
2)増分を計算します= arr.length / 2 = 5
3)グループ8-> 3、9- > 5、1- > 4、7- > 6、2- > 0
3)および最初のラウンドでポジションを交換する必要があるかどうかを判断する
//根据length/2 = 5 ,步长 = 5
for(int i = 5; i<arr.length; i++) {
//如果当前元素大于加上步长后的那个元素,说明交换
for(int j=i-5;j>=0;j-=5) {
if(arr[j] > arr[j+5]) {
temp = arr[j];
arr[j]=arr[j+5];
arr[j+5]=temp;
}
}
}
System.out.println("希尔排序1轮后:"+Arrays.toString(arr));
第二ラウンド
//步长 = 5/2 =2
for(int i = 2; i<arr.length; i++) {
for(int j=i-2;j>=0;j-=2) {
if(arr[j] > arr[j+2]) {
temp = arr[j];
arr[j]=arr[j+2];
arr[j+2]=temp;
}
}
}
System.out.println("希尔排序2轮后:"+Arrays.toString(arr));
第三ラウンド
//步长 = 2/2 = 1
for(int i = 1; i<arr.length; i++) {
for(int j=i-1;j>=0;j-=1) {
if(arr[j] > arr[j+1]) {
temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println("希尔排序3轮后:"+Arrays.toString(arr));
*/
実行結果これ
は私のJavaコードを楕円形にしたもので、怠惰すぎてもう一度pythonを入力できません。
Python統合後の取引所ベースのHillソートコードは次のとおりです。
def shellSort(arr):
temp = 0
gap = len(arr)
while gap>1:
gap = int(gap/2)
for i in range(gap,len(arr),1):
for j in range(i-gap,-1,-gap):
if arr[j]>arr[j+gap]:
temp = arr[j]
arr[j] = arr[j+gap]
arr[j+gap] = temp
ただし、バブルソートと同様に、2つの要素の値が交換されるため、時間効率は非常に低くなります。したがって、要素を適切な位置に移動し、ソートを挿入した後に要素を挿入する操作を改善する必要があります。
def shellSort2(arr):
temp = 0
gap = len(arr)
while gap>1:
gap = int(gap/2)
for i in range(gap,len(arr),1):
j = i
temp = arr[j]
if arr[j]<arr[j-gap]:
#先移位
while(j-gap>=0 and temp<arr[j-gap]):
arr[j] = arr[j-gap]
j -= gap
#后插入
arr[j] = temp
これは、モバイルエクスチェンジロケーションを使用するHillソートコードです。次に、時間効率が向上するかどうかをテストします。時間モジュールとランダムモジュールをインポートして、8000要素のランダム配列を作成します。具体的なコードは次のとおりです。
import time
import random
#arr = [8,9,1,7,2,3,5,4,6,0]
arr = [0 for i in range(8000)]
for i in range(8000):
arr[i]=random.randint(0,8000)
def shellSort(arr):
temp = 0
gap = len(arr)
while gap>1:
gap = int(gap/2)
for i in range(gap,len(arr),1):
for j in range(i-gap,-1,-gap):
if arr[j]>arr[j+gap]:
temp = arr[j]
arr[j] = arr[j+gap]
arr[j+gap] = temp
def shellSort2(arr):
temp = 0
gap = len(arr)
while gap>1:
gap = int(gap/2)
for i in range(gap,len(arr),1):
j = i
temp = arr[j]
if arr[j]<arr[j-gap]:
#先移位
while(j-gap>=0 and temp<arr[j-gap]):
arr[j] = arr[j-gap]
j -= gap
#后插入
arr[j] = temp
print("交换式希尔排序:")
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
shellSort(arr)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
#print(arr)
print("插入式希尔排序:")
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
shellSort2(arr)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
#print(arr)
操作結果を図に示し
ます。時間効率が元の9秒から1秒未満に大幅に改善されていることがわかります。共有が終了しました。