排序演算法(三)

高傑才_Android發表於2014-11-01

2. 插入排序—希爾排序(Shell Sort)

希爾排序是1959年由D.L.Shell提出來的,相對直接排序有較大的改進。希爾排序又叫縮小增量排序。

基本思想:

    基本思想:演算法先將要排序的一組數按某個增量d(n/2,n為要排序數的個數)分成若干組,每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。當增量減到1時,進行直接插入排序後,排序完成。

操作方法:

    1、選擇一個增量序列t1,t2,....,tk,其中ti>tj,tk=1;

    2、按增量序列的個數k,對序列進行k趟排序;

    3、每趟排序,根據對應的增量ti,將帶排序列分割成若干長度為m的子序列,分別對個子序列進行直接插入排序。僅增量因子為1時,整個序列為一個表來處理,表長度即為整個序列的長度。

希爾排序的示例:

演算法實現:

 

我們簡單處理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n為要排序數的個數

 

即:先將要排序的一組記錄按某個增量dn/2,n為要排序數的個數)分成若干組子序列,每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。繼續不斷縮小增量直至為1,最後使用直接插入排序完成排序。

 

public class ShellSort3 {

    public static void main(String[] args) {
        int[] a = {12,43,65,7632,31,76,21,79,20};
        System.out.println("排序前");
        for(int i=0; i<a.length; i++){
            System.out.print(a[i]+"   ");
        }
        System.out.println();
        shellSort(a, a.length);
        System.out.println("排序後");
        for(int i=0; i<a.length; i++){
            System.out.print(a[i]+"   ");
        }
        
    }
    
    public static void shellSort(int[] a,int n){
        int d,x,i,j;
        d=n/2;                //設定增量
        while(d>=1){        //當增量小雨1的時候推出迴圈,說明我們的資料已經拍好
            for(i=d; i<n; i++){
                x = a[i];    //獲取序列中的下一個資料,也就是我們要插入的資料
                j = i-d;    //序列中的前一個資料
                while(j>=0 && x<a[j]){
                    a[j+d] = a[j];
                    j -= d;
                }
                a[j+d] = x;
            }
            d/=2;
        }
    }
}

 

希爾排序時效分析很難,關鍵碼的比較次數與記錄移動次數依賴於增量因子序列d的選取,特定情況下可以準確估算出關鍵碼的比較次數和記錄的移動次數。目前還沒有人給出選取最好的增量因子序列的方法。增量因子序列可以有各種取法,有取奇數的,也有取質數的,但需要注意:增量因子中除1 外沒有公因子,且最後一個增量因子必須為1。希爾排序方法是一個不穩定的排序方法。

相關文章