前言
在我寫的插入排序詳解中,有可能出現下面的問題。
數組 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、希爾排序基本介紹
希爾排序是希爾(Donald Shell)於1959年提出的一種排序算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱爲縮小增量排序。
希爾排序法基本思想是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。
2、希爾排序思路圖解
動圖演示:
小結希爾排序規則:
先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,具體算法描述:
- 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列個數k,對序列進行k 趟排序;
- 每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列作爲一個表來處理,表長度即爲整個序列的長度。
3、代碼實現
希爾排序是在插入排序上進行優化的,多了一步分組操作。如果插入排序不理解的話,可以轉到我寫的《排序算法之插入排序詳解》中,那有詳細介紹。
public class ShellSort {
public static void main(String args[]) {
int arr[] = { 101, 34, 119, 1, -1, 89 };
// 增量 gap, 並逐步的縮小增量
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
// 從第 gap 個元素,逐個對其所在的組進行直接插入排序
for (int i = gap; i < arr.length; i++) {
int j = i;
int temp = arr[j];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && temp < arr[j - gap]) {
// 移動
arr[j] = arr[j - gap];
j -= gap;
}
// 當退出 while 後,就給 temp 找到插入的位置
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}