希爾(shell)排序是一種插入排序,同時也叫縮小增量排序,算是直接插入排序的乙個優化演算法,以其設計者希爾(donald shell)的名字命名,該演算法由 1959 年公布。
將待排序列以一定的步長分成子串行,把子序列進行排序,然後會繼續以更小的步長進行分子序列,並將子串行排序,最終演算法以步長為 1 進行排序。當步長為 1 時,演算法變為直接插入排序,這就保證了資料一定會被全部排序。因此步長的選定很重要。
如待排序列為9個元素,每個元素的下標為0-8,則我們選擇初始步長為3,分組,按下標分組分為,,三組,把這三組在內部進行排序,排序完後再以步長為1,進行排序。則最後對整個序列進行一次直接插入排序即可。
def shellsort(input_list):
length = len(input_list)
if length == 0:
return
sorted_list = input_list
#我們這裡取第一次步長為序列長度的一半
#n記錄縮小增量的次數標誌
n = 1
d = length//2
while d > 0:
for i in range(d,length):
#j是在第i個元素前面的第d個元素
j = i - d
#臨時記錄i此時的元素
temp = sorted_list[i]
#若下標大於等於0且後面的元素temp小於temp前面第d個元素
#便把前面那個大的元素賦值給湖面temp元素
while j >= 0 and temp < sorted_list[j]:
sorted_list[j+d] = sorted_list[j]
j -=d
#在把temp記錄的後面的小的元素賦值給前面那個大元素
#完成:如果後面元素小於前面元素,就調換來那個元素的位置
sorted_list[j+d] = temp
#增量繼續減小
d //=2
print("%dth"%n)
print(sorted_list)
#記錄增量減小的次數標誌
步長的選擇是希爾排序的重要部分,只要最終步長為1任何步長序列都可以工作。演算法最開始以一定的步長進行排序。然後會繼續以一定步長進行排序,最終演算法以步長為1進行排序。當步長為1時,演算法變為插入排序,這就保證了資料一定會被排序.步長序列的不同,會導致最壞的時間複雜度情況的不同。因此步長的選擇是關鍵的,一般初始步長用len/2,用這樣步長序列的希爾排序比插入排序要快,甚至在小陣列中比快速排序和堆排序還快,但是在涉及大量資料時希爾排序還是比快速排序慢。
雖然在每次把後面更小的元素換到前面是穩定的,但是在不同的子串行中,還是會打亂相等元素的位置
例如序列,其中為區分兩個相等的4,把第乙個出現的4記為4',取步長為2,則分為、、三個子串行,
則第一次比較之後為、、,把這三個子串行合成乙個子串行為,顯然兩個4的序列位置反過來了。故shell排序是一種不穩定的排序演算法。
直接插入排序是穩定的;而希爾排序是不穩定的。
直接插入排序更適合於原始記錄基本有序的集合。
希爾排序的比較次數和移動次數都要比直接插入排序少,當n越大時,效果越明顯。
直接插入排序也適用於鏈式儲存結構;希爾排序不適用於鏈式結構。因為斷鏈之後要在重新恢復鏈式結構就會很大程度上增加時間複雜度,增加的時間複雜度可能超過希爾排序家相比直接插入排序所較少的複雜度,反而適得其反。
排序演算法之希爾排序
希爾排序實際上是一種分治思想的插入排序。插入排序不說了,不清楚看這裡 分治思想,對增量為dk,dk遞減,開始很多小序列,最後為乙個大序列 相對直接插入排序,在希爾排序中,只不過增量不是1,而是dk 較好的增量序列是2 k 1,2 k 1 1,7,3,1,這樣可使shell排序時間複雜度達到o n 1...
排序演算法之希爾排序
希爾排序 shell sort 又稱為縮小增量排序,輸入插入排序演算法,是對直接排序演算法的一種改進。本文介紹希爾排序演算法。對於插入排序演算法來說,如果原來的資料就是有序的,那麼資料就不需要移動,而插入排序演算法的效率主要消耗在資料的移動中。因此可知 如果資料的本身就是有序的或者本身基本有序,那麼...
排序演算法之希爾排序
希爾排序,突破了 通過交換相鄰元素進行排序的任何演算法平均需要 n 2 的二次時間限制 通過比較相距一定間隔的元素來工作。使用乙個增量序列 h1 1,h2,ht,在使用乙個 增量h的一趟排序後,對於每乙個i滿足pdata i pdata i h 即此時序列是h排序的 各趟 比較所用的距離逐漸減小,直...