標籤:不同的 基本 變化 定義 ring amp 說明 string 距離
1.基本思想
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。
2.實現原理
對於n個待排序的數列,取一個小於n的整數gap(gap被稱為步長)將待排序元素分成若干個組子序列,所有距離為gap的倍數的記錄放在同一個組中;然後,對各組內的元素進行直接插入排序。 這一趟排序完成之後,每一個組的元素都是有序的。然後減小gap的值,並重複執行上述的分組和排序。重複這樣的操作,當gap=1時,整個數列就是有序的。
3.代碼執行個體
(1)代碼:
/** * 對希爾排序中的單個組進行排序 * <p> * 參數說明: * a -- 待排序的數組 * n -- 數組總的長度 * i -- 組的起始位置 * gap -- 組的步長 * <p> * 組是"從i開始,將相隔gap長度的數都取出"所組成的! */ public static void groupSort(int[] a, int n, int i, int gap) { //列印分組 System.out.print("gap="+gap+" ["); //列印第一個比較的元素 System.out.print(a[i]); //直接插入排序 for (int j = i + gap; j < n; j += gap) { //被比較的元素 System.out.print(" "+a[j]); // 如果a[j] < a[j-gap],則尋找a[j]位置,並將後面資料的位置都後移。 if (a[j] < a[j - gap]) { int tmp = a[j]; int k = j - gap; while (k >= 0 && a[k] > tmp) { a[k + gap] = a[k]; k -= gap; } a[k + gap] = tmp;// System.out.print(" ("+a[j]+"<-->"+a[j-gap]+")"); } } System.out.println("]"); } /** * 希爾排序 * <p> * 參數說明: * a -- 待排序的數組 * n -- 數組的長度 */ public static void shellSort(int[] a, int n) { // gap為步長,每次減為原來的一半。 for (int gap = n / 2; gap > 0; gap /= 2) { // 共gap個組,對每一組都執行直接插入排序 for (int i = 0; i < gap; i++) groupSort(a, n, i, gap); System.out.printf("after sort:"); for (int i = 0; i < a.length; i++) System.out.printf("%d ", a[i]); System.out.println(); System.out.println(); } } public static void main(String[] args) { int i; int a[] = {80, 30, 60, 40, 20, 10, 50, 70,100}; System.out.printf("before sort:"); for (i = 0; i < a.length; i++) System.out.printf("%d ", a[i]); System.out.println(); System.out.println(); shellSort(a, a.length); }
(2)結果:
before sort:80 30 60 40 20 10 50 70 100
gap=4 [80 20 100]
gap=4 [30 10]
gap=4 [60 50]
gap=4 [40 70]
after sort:20 10 50 40 80 30 60 70 100
gap=2 [20 50 80 60 100]
gap=2 [10 40 30 70]
after sort:20 10 50 30 60 40 80 70 100
gap=1 [20 10 50 30 60 40 80 70 100]
after sort:10 20 30 40 50 60 70 80 100
4.演算法分析
(1)希爾排序時間複雜度
希爾排序的時間複雜度與增量(即,步長gap)的選取有關。例如,當增量為1時,希爾排序退化成了直接插入排序,此時的時間複雜度為O(N²),而Hibbard增量的希爾排序的時間複雜度為O(N3/2)。
(2)希爾排序空間複雜度
空間複雜度是O(1) 因為只有一個緩衝單元。
(3)希爾排序穩定性
希爾排序是不穩定的演算法,它滿足穩定演算法的定義。對於相同的兩個數,可能由於分在不同的組中而導致它們的順序發生變化。
演算法穩定性 -- 假設在數列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;並且排序之後,a[i]仍然在a[j]前面。則這個排序演算法是穩定的!
5.排序特點
我們知道一次插入排序是穩定的,但在不同的插入排序過程中,相同的元素可能在各自的插入排序中移動,最後其穩定性就會被打亂,所以希爾排序是不穩定的。
希爾排序的時間效能優於直接插入排序,原因如下:
(1)當檔案初態基本有序時直接插入排序所需的比較和移動次數均較少。
(2)當n值較小時,n和n2的差別也較小,即直接插入排序的最好時間複雜度O(n)和最壞時間複雜度0(n2)差別不大。
(3)在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作為距離排過序,使檔案較接近於有序狀態,所以新的一趟排序過程也較快。
因此,希爾排序在效率上較直接插人排序有較大的改進。
希爾排序的平均時間複雜度為O(nlogn)。
排序演算法(3)--Insert Sorting--插入排序[3]--Shell Sort--希爾排序