注:本文參考
在講解希爾排序之前,我們有必要先回頭看一下插入排序的問題。插入排序不管陣列分布時怎麼樣的,都是一步步的對元素進行比較,移動,插入。比如[5,4,3,2,1,0]這種倒序序列,陣列末端的0要回到首位很費勁,比較和移動元素均需n-1次。這時就引出了希爾排序。
希爾排序是希爾(donald shell)於2023年提出的一種排序演算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的更高效的版本。該演算法是突破o(n^2)的第一批演算法之一。
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序。隨著增量逐漸減小,每組包含的數字越來越多,當增量減至1時,整個檔案恰好被分成一組,演算法便終止。
我們來看下希爾排序的基本步驟,我們選擇增量gap = length/2,縮小增量繼續以gap = gap/2 的方式,這種增量選擇我們可以用乙個序列來表示,的增量序列。
原始陣列 以下資料元素顏色相同的為一組
初始增量 gap = length/2 = 5,所以整個陣列被分為5組,即從第一位置的數字開始向後+n*gap為同一組,所以第一次增量後5組為[8,3],[9,5],[1,4],[7,6],[2,0]
對這五組分別進行插入排序,例如[8,3]插入排序後會交換位置[3,8],[9,5]插入排序後會交換位置為[5,9]等等。所以執行後會將小的數字放在陣列的前面。
然後繼續減小增量gap=5/2 = 2,陣列被分為2組,即從第一位置的數字開始向後+n*gap為同一組,蒐衣第二次增量後2組為[3,1,0,9,7] 和 [5,6,8,4,2]。如下圖所示
對以上兩組再分別進行插入排序,在[3,1,0,9,7]中會變為[0,1,3,7,9], [5,6,8,4,2]會變為[2,4,5,6,8],如下圖所示,可以看到整個陣列的有序程度更進一步了。
再縮小增來gap=2/2 = 1 ,此時整個陣列為1組[0,2,1,4,3,5,7,6,9,8],如下圖所示
經過上面的「巨集觀調控」,整個陣列已經基本有序。此時再對整個陣列進行插入排序,只需進行少量的交換即可變為有序陣列。
1.交換式實現方式
12.移位式實現方式/**2
* 交換式排序3*
@param
array4*/
5public
static
void sort1(int
array)18}
19}20 }
11)第一層for迴圈用於確定分組大小,這裡選用對陣列大小減半的的方式,後面每次對原分組減半,直到分組大小為1/**2
* 移位式排序3*
@param
array4*/
5public
static
void sort2(int
array)
16if(insertindex !=startindex)19}
20}21 }
2)第二層for迴圈表示從第gap個元素開始(這裡說明下為什麼從第gap個元素開始:第gap個元素剛好為分組中的第一組的第二個元素,因為我們的插入排序為從第二個元素開始向前比較),向後依次執行插入排序,直到最後乙個元素
3)while迴圈用於對每個分組進行插入排序(交換式為當找到比插入元素大的元素時,交換兩個元素。移位式為當找到比插入元素大時,將那個元素向後移動gap位,最後再將待插入元素放在空缺的位置即可)
從我們的分析可知,希爾排序中對於增量序列的選擇十分重要,直接影響到希爾排序的效能。我們上面選擇的增量序列,其最壞時間複雜度依然位o(n^2),一些經過優化的增量序列如hibbard經過複雜證明可使得最壞時間複雜度為o(n3/2)。
與前面的排序演算法相同,我們依然生成10萬個隨機數的陣列,使用插入排序方法進行排序,看其執行時間。測試**如下
1可以看到希爾排序演算法比插入排序更快,10萬個資料的陣列排序大概需要300多毫秒時間。下篇我們將介紹快速排序演算法,排序效率是否會更高呢?一起期待!public
static
void
main(string args)
6long begin =system.currenttimemillis();
7sort2(array);
8 system.out.println("總耗時="+(system.currenttimemillis()-begin));
9 }
希爾排序是乙個基於插入排序的演算法,解決了當待排序陣列倒序時使用插入排序演算法要移動多次的耗時操作。希爾排序的核心演算法為先將待排序陣列進行分組進行小範圍的排序,每次分組排序後待排序陣列就會在大範圍上更有序。當分組大小減小到1時,待排序陣列已經基本有序,此時再執行插入排序,可以確保移動或交換的次數更少,從而達到提公升排序效率的目的。
注:本文參考
經典排序演算法之希爾排序
前面的直接插入演算法,以抓牌為例,假設手氣比較好,抓牌的順序是從a直到k,那麼在這整個過程中都無需進行任何的插入動作,只需要將每次抓到的牌放在最後即可。假設現在手上已經抓到的牌的順序中逆序比較少,則抓牌的過程中插入操作就越少。因此,對於基本有序的序列排序,直接插入排序的效能是比較好的。這裡的基本有序...
經典排序演算法 希爾排序Shell sort
經典排序演算法 希爾排序shell sort 希爾排序shell sort是基於插入排序 的一種改進,同樣分成兩部分,第一部分,希爾排序介紹 第二部分,如何選取關鍵字,選取關鍵字是希爾排序的關鍵 第一塊希爾排序介紹 準備待排陣列 6 2 4 1 5 9 首先需要選取關鍵字,例如關鍵是3和1 第一步分...
經典排序演算法 希爾排序Shell sort
經典排序演算法 希爾排序shell sort 經典 排序演算法 希爾排序shell sort 希爾排序shell sort是基於插入排序 的一種改進,同樣分成兩部分,第一部分,希爾排序介紹 第二部分,如何選取關鍵字,選取關鍵字是希爾排序的關鍵 第一塊希爾排序介紹 準備待排陣列 6 2 4 1 5 9...