排序(二)希爾排序

本節主要簡單介紹一下希爾排序算法,希爾排序(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;
    }

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

四、總結

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章