1. 程式人生 > >演算法 希爾排序小述

演算法 希爾排序小述

一、概述

本節主要簡單介紹一下希爾排序演算法,希爾排序(Shell’s Sort)是插入排序的一種,又稱“縮小增量排序”(Diminishing Increment Sort),是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止,摘自百度百科。從定義描述來看,很不好理解,反正我第一次看的時候是一臉懵逼,下面我就用自己的理解簡單分析下。

二、分析

其實我覺得,希爾排序就是根據特定的規則進行多次的直接插入排序操作,就以陣列[ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]這個陣列為例:

上面說的規則就是增量的計算,直接插入排序的增量為1,而我們希爾排序的增量是我們自己定義的,一般情況是中分取整,本例中則為10/2=5、5/2=2、2/2=1;所以我們需要進行3次直接插入排序,每次直接插入排序的增量分別為5、2、1

上面說的多次的求法,我們已經知道是3次,通常規則和次數都是相互對應的,但增量的計算方法我們是可以根據不同情況而變的。

增量為5的時候,我們第一輪的直接插入排序是怎樣的呢?首先我們會將陣列[ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]根據增量分組,具體每組情況如下:
第1組:[9, 4],只有2個元素;
第2組:[8, 3],只有2個元素;
第3組:[7, 2],只有2個元素;
第4組:[6, 1],只有2個元素;
第5組:[5, 0],只有2個元素;
之後我們每組分別進行直接插入排序操作,思路就是有序和無序兩部分,無序不斷插入到有序之中,不清楚的可以檢視我的

直接插入排序的介紹:
第1組:直接插入排序後[4, 9];
第2組:直接插入排序後[3, 8];
第3組:直接插入排序後[2, 7];
第4組:直接插入排序後[1, 6];
第5組:直接插入排序後[0, 5];
所以當第1輪增量為5的迴圈結束後,原始資料變為[4, 3, 2, 1, 0, 9, 8, 7, 6, 5]

在這裡插入圖片描述

增量為2的時候,方法思路同上,首先我們將之分組,每組情況如下:
第1組:[4, 2, 0, 8, 6],有5個元素;
第2組:[3, 1, 9, 7, 5],有5個元素;
之後我們每組分別進行直接插入排序操作:
第1組:直接插入排序後[0, 2, 4, 6, 8];
第2組:直接插入排序後[1, 3, 5, 7, 9];
所以當第2輪增量為2的迴圈結束後,原始資料變為[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

在這裡插入圖片描述

增量為1的時候,已經跟我們直接插入排序的演算法完成一樣了,現在只有一組資料了:
第1組:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],全部元素;
之後我們每組分別進行直接插入排序操作:
第1組:直接插入排序後[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],因為這個序列比較特殊,當增量為1的時候不需要移位插入;

在這裡插入圖片描述

如果對於希爾排序還不是很清晰,可以結合程式碼看下哦,這樣我覺得效果更佳

三、程式碼展示

希爾排序演算法的程式碼如下,主要分為3個迴圈體,外層迴圈控制要進行直接插入排序的次數,內兩層為直接插入排序演算法:

    private static int[] shellSort(int[] array) {
        int length = array.length;
        // 分為幾輪直接插入排序
        for(int gap = length/2; gap>=1; gap/=2) {
            int i = gap;
            for(; i<length; i+=gap){
                int temp = array[i];
                int j = i-gap;
                for(; j>=0&&temp<array[j]; j-=gap){
                    array[j+gap] = array[j];
                }
                array[j+gap] = temp;
            }
        }
        return array;
    }

值得注意的是,由於希爾排序會進行多次插入排序,我們知道一次插入排序是穩定的,不會改變相同元素的相對順序,但在不同的插入排序過程中,相同的元素可能在各自的插入排序中移動,最後其穩定性就會被打亂,所以希爾排序是不穩定的。

四、總結

當然程式碼編寫並不是固定的,肯定會有很多變形格式,其實我們研究的也是希爾排序的思想和每種寫法的效率問題。如果想要檢視更多演算法基礎,去我的部落格目錄裡檢視吧,因為關於每塊知識點的介紹,部落格單節寫的比較零散,不容易查詢。