希爾排序
先將整個待排序的序列分割成若干個子序列分別進行直接插入排序,當整個序列的元素“基本有序”時,再對全體進行一次直接插入排序。
需要注意的是,子序列的構成不是簡單的“逐段分割”,而是將相隔某個“增量”的記錄組成一個子序列,如第一趟增量爲5,第二趟增量可以爲3等等。
這個增量習慣上用字母h來表示這個增量, 常用的h序列由Knuth提出,該序列從1開始,通過如下公式產生:h = 3 * h +1。
例如下述過程:
希爾排序穩定性
希爾排序是不穩定的算法,它滿足穩定算法的定義。對於相同的兩個數,可能由於分在不同的組中而導致它們的順序發生變化。
希爾排序時間複雜度
希爾排序的時間複雜度與增量(即步長gap)的選取有關。如,當增量爲1時,希爾排序退化爲直接插入排序,此時的時間複雜度爲0(N),而Hibbard增量的希爾排序的時間複雜度爲0(N^3/2)。
Java實現
package acm; /*希爾排序 * 2017.11.22 * 希爾排序算法減小數據項的間隔再進行排序,依次進行下去,進行這些排序時的數據項 * 之間的間隔被稱爲增量,習慣上用字母h來表示這個增量。 * 常用的h序列由Knuth提出,該序列從1開始,通過如下公式產生:h = 3 * h +1 */ public class ShellSort { static void shellSort(int[] ary){ int h = 1; //計算h可取的最大值 while(h <= ary.length/3){ h = 3*h+1; } while(h>0){ for(int i=h;i<ary.length;i+=h){ if(ary[i]<ary[i-h]){ int temp = ary[i]; int j = i-h; while(j>=0 && ary[j]>temp){ ary[j+h] = ary[j]; j-=h; } ary[j+h] = temp; for(int ele:ary){ System.out.print(ele+","); } System.out.println("");//換行 } } h = (h-1)/3; } } public static void main(String[] args){ int[] ary = new int[]{49,38,65,97,76,13,27,49,55,4}; shellSort(ary); } }