希爾排序 插入排序的升級

直接插入排序我們是知道的,它比冒泡和選擇快的原因是數據交換的次數相對較少,不像冒泡那樣,每次內循環遍歷時兩個兩個數比較然後換來換去,如果是完全反序的,那就得每次都進行交換操作,交換操作可比邏輯判斷操作要費時多,這也是之前問的,爲什麼時間複雜度明明差不多,但運行時間卻天差地別,冒泡排序排10萬個數據的時候居然用了1分多種。
然而要減少交換操作,那就需要序列向有序化靠攏,這樣實際的交換數據操作減少很多,時間也會大幅減少。
如何使數列偏於有序化呢。這裏有個很重要的思想,那就是分段。
我們可以讓一個長序列,分爲好多段或組,給它們分別進行排序,那就變得基本有序了。
何爲基本有序?
用升序來說,就是前面的數據普遍偏小,後面的數據普遍偏大.
比如一個長爲10的數據。
 1 9 3  4 5 6  6 1 8
這不是基本有序,看似 除了 9 和1     剩下的1 3 4 56 6 8挺有序的,但9在很前面,1在很後面,這不能算基本有序
再比如一個長爲10的數據
3 21   6 5  4  6  9   87 
你一看,我天,什麼321 ,654 6,987這全反過來了,亂的一匹,但這勉強算基本有序,因爲前三位數也基本是最小的三個,中間4位位數也是不大不小的四個,最後3個也是最大的三個數。
所以該如何分組使得數列基本有序呢?
比如9個數。
能讓前三個一排序?中間三個一排序?後面三個一排序嗎?
顯然是不能的!!

應該使前面三個普遍小於中間三個,讓中間三個普遍小於後面三個。
那麼這種分組方式就出來了:
讓9個數中的 1   4   7號位置排序  2 5 8號位置排序   3,6,9號位置排序。

希爾排序就使用的是這個思想。

首先設置一個dka表示一組元素的多少隔。
使dka慢慢增大。
最後dka增長爲數列長度時,其實就只有一組了,那就變成了直接插入排序了。此時的數列已經基本有序了,所以執行的時間會大大減少。

反過來我們也可以直接設置有多少組,使組數慢慢減少爲1,也是相同的道理。
比如我設置一個表示組數多少的數組dka[];
那10個數舉例
我設置dka[]爲{5,3,1}
5組就代表從第6個數開始,第6個數和第1個數排序,第7個和第二個數排序。。。。。第10個和第5個數排序
3組....
代碼如下


由於1萬個數據對於希爾來說太快了,所以這次使用了10萬個數據測試結果

這是dka爲{5,3,1}的情況,只用了1.5秒

如果把分組細化,效率也會更快
下面是dka爲{50,20,10,5,3,1}




dka爲{300,150,100,50,20,10,5,3,1};


之前說的幾種排序,冒泡。選擇。插入的平均時間複雜度都在0(n^2)的級別

希爾的時間複雜度卻達到了蛻變  O(n^1.3)


至於穩定性。我們知道直接插入是穩定的,可能會猜測進化版不會不穩定吧。
結果還真是不穩定,因爲有了分組,而且每組的每個數據都相距甚遠(dka長) 所以插入數據的時候有非常頻繁的跳躍式插入,這樣肯定就是不穩定的了,至於如何改進爲穩定的,我之前的博客有寫過一個方法,有興趣,可以去看看。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章