希爾排序
1.概述
希爾排序是希爾(Donald Shell)於1959年提出的一種排序算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之后的一個更高效的版本,也稱為縮小增量排序。
首先我們知道直接插入排序的時間復雜度最低的時候應該是序列基本有序,效率最高,在待排序的記錄個數較少時,效率較高。基於這個基礎理論,希爾排序的基本思想如下:
先將整個待排記錄序列分割成若干子序列,分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行一次直接插入排序。
技巧:
子序列的構成不是簡單地“逐段分割”
將相隔某個增量dk的記錄組成一個子序列
讓增量dk逐趟縮短(例如依次取5,3,1)
直到dk=1為止。
優點:
小元素跳躍式前移
最后一趟增量為1時,序列已基本有序
平均性能優於直接插入排序
如何選擇最佳d序列,目前尚未解決
最后一個增量值必須為1,無除1以外的公因子
不宜在鏈式存儲結構上實現
二、過程
這部分參考https://www.cnblogs.com/chengxiao/p/6104371.html, 主要是圖畫的特別好
我們來看下希爾排序的基本步驟,在此我們選擇增量gap=length/2,縮小增量繼續以gap = gap/2的方式,這種增量選擇我們可以用一個序列來表示,{n/2,(n/2)/2...1},稱為增量序列。希爾排序的增量序列的選擇與證明是個數學難題,我們選擇的這個增量序列是比較常用的,也是希爾建議的增量,稱為希爾增量,但其實這個增量序列不是最優的。此處我們做示例使用希爾增量。
三.算法分析
四、完整代碼
public class ShellSort {
public static void sort(int[] array) {
int inner, outer;
int temp;
int h = 1;
while (h <= array.length / 3) {
h = h * 3 + 1;
}
while (h > 0) {
for (outer = h; outer < array.length; outer++) {
temp = array[outer];
inner = outer;
while (inner > h - 1 && array[inner - h] >= temp) {
array[inner] = array[inner - h];
inner -= h;
}
array[inner] = temp;
}
h = (h - 1) / 3;
}
}
public static void main(String[] args) {
int [] array = {5,3,0,2,4,1,0,5,2,3,1,4};
System.out.println("Before: " + Arrays.toString(array));
sort(array);
System.out.println("After: " + Arrays.toString(array));
}
}