排序演算法(3)--Insert Sorting--插入排序[3]--Shell Sort--希爾排序

來源:互聯網
上載者:User

標籤:不同的   基本   變化   定義   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--希爾排序

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.