イベントアドレス: CSDN 21 日間学習チャレンジ
学問の最大の理由は凡庸さを取り除くことであり、一日も早く、人生がより華やかになります。
1. コンセプト
希尔排序
は、缩小增量排序
不安定なソート アルゴリズムです。では、Hill ソートはどのように増分を減らしますか? まず、ソートするシーケンスを特定の添字の増分でグループ化し、各グループをソートします. 増分が徐々に減少するにつれて、各グループにはますます多くの要素/要素が含まれます直接插入排序算法
. 增量
1 にすると、ファイル全体が 1 つのグループに分割されるだけなので、アルゴリズムは終了します。
アルゴリズムの考え方は
、最初にソートする数値のグループを特定の増分 d でいくつかのグループに分割し、各グループに記録されている添字が d だけ異なるようにし、各グループのすべての要素をソートしてから、a を使用することです。それらをグループ化して各グループ内でソートするには、より小さな増分を使用します。増分が 1 になると、ソートする番号全体が 1 つのグループに分割され、ソートが終了します。
一般に、シーケンスの半分が最初に増分として取得され、増分が 1 になるまで毎回半分になります。合計 10 個の要素がある場合、インクリメンタル シーケンスの値は 5、2、1 です。
2. 疑似コード
d = A.length / 2
while d > 0
for i = 1 to d
for j = i + d to A.length by d
tmp = A[j]
k = j - d
while k > 0 and A[k] > tmp
A[k + d] = A[k]
k = k - d
A[k + d] = tmp
d = d / 2
3.コアコードの実装
3.1 Java 版
public static void main(String[] args){
int[] array={
49,38,65,97,76,13,27,49,78,34};
System.out.println("排序之前:");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
//希尔排序
int gap = array.length;
while (true) {
gap /= 2; //增量每次减半
for (int i = 0; i < gap; i++) {
for (int j = i + gap; j < array.length; j += gap) {
//这个循环里其实就是一个插入排序
int k = j - gap;
while (k >= 0 && array[k] > array[k+gap]) {
int temp = array[k];
array[k] = array[k+gap];
array[k + gap] = temp;
k -= gap;
}
}
}
if (gap == 1)
break;
}
System.out.println();
System.out.println("排序之后:");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
3.2 Python のバージョン
def shell_sort(seq):
seq_len = len(seq)
step = seq_len >> 1
# 增量小于1说明最终排序已完成
while step:
for i in range(step, seq_len):
# j记录元素原始位置,用于查找前面所有小于当前元素的元素
j = i
while seq[j] < seq[j-step] and j-step >= 0:
seq[j], seq[j-step] = seq[j-step], seq[j]
# 改变下标,查看前面是否还有更小的值
j -= step
print(f"增量{
step}的排序:", seq)
# 每次增长减小一半
step = step >> 1
4. アルゴリズム効率分析
ヒルソートの実行時間はインクリメントシーケンスに依存します。優れたインクリメンタル シーケンスの一般的な特徴:
- 最終増分は 1 でなければなりません
- シーケンス内の値が互いに倍数になる状況を避けるようにしてください。
空间复杂度
対象: O(1)
时间复杂度
対象: O(n^(1.3—2))