1. 程式人生 > >【S-排序】python實現八大排序演算法之4-希爾排序ShellSort

【S-排序】python實現八大排序演算法之4-希爾排序ShellSort

希爾排序ShellSort

起源:

  • 直接插入法的改進演算法。希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。該方法因DL.Shell於1959年提出而得名。

希爾排序【縮小增量排序演算法】基本思想:

  • 希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。
  • 簡單插入排序很循規蹈矩,不管陣列分佈是怎麼樣的,依然一步一步的對元素進行比較,移動,插入,比如[5,4,3,2,1,0]這種倒序序列,陣列末端的0要回到首位置很是費勁,比較和移動元素均需n-1次。而希爾排序在陣列中採用跳躍式分組的策略,通過某個增量將陣列元素劃分為若干組,然後分組進行插入排序,隨後逐步縮小增量,繼續按組進行插入排序操作,直至增量為1。希爾排序通過這種策略使得整個陣列在初始階段達到從巨集觀上看基本有序,小的基本在前,大的基本在後。然後縮小增量,到增量為1時,其實多數情況下只需微調即可,不會涉及過多的資料移動。
  • 我們來看下希爾排序的基本步驟,在此我們選擇增量gap=length/2,縮小增量繼續以gap = gap/2的方式,這種增量選擇我們可以用一個序列來表示,{n/2,(n/2)/2…1},稱為增量序列。希爾排序的增量序列的選擇與證明是個數學難題,我們選擇的這個增量序列是比較常用的,也是希爾建議的增量,稱為希爾增量,但其實這個增量序列不是最優的。此處我們做示例使用希爾增量.
  • 希爾排序中對於增量序列的選擇十分重要,直接影響到希爾排序的效能。我們上面選擇的增量序列{n/2,(n/2)/2…1}(希爾增量),其最壞時間複雜度依然為O(n2),一些經過優化的增量序列如Hibbard經過複雜證明可使得最壞時間複雜度為O(n3/2)。增量因子序列可以有各種取法,有取奇數的,也有取質數的,但需要注意:增量因子中除1 外沒有公因子,且最後一個增量因子必須為1。希爾排序方法是一個不穩定的排序方法

希爾排序【縮小增量排序演算法】程式碼實現:
- 在程式碼實現中,我們可以不用這麼按部就班地處理完一組再調轉回來處理下一組,可以在迴圈裡面進行跨組比較。我理解的在普通的插入法外面增加一個迴圈,控制Gap,並逐步減少gap的值。
- 基礎的插入法排序是兩重迴圈,希爾排序是三重迴圈,最外面一重迴圈,控制增量gap,並逐步減少gap的值。二重迴圈從下標為gap的元素開始比較,依次逐個跨組處理。最後一重迴圈是對組內的元素進行插入法排序。
- 這樣進行排序的有點在於每次迴圈,整個序列的元素都將小元素的值逐步向前移動,數值比較大的值向後移動。

'''
Creat by HuangDandan
2018-08-13
[email protected]
希爾排序是直接插入法排序的改進 希爾排序的原理: 希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。 希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序; 隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。 '''
#在直接插入的基礎上增加增量,加一個迴圈,將其他兩重迴圈中的增量1改成增量gap #下面插入法採用的是移動法 def ShellInsertSort(Lst): gap = int(len(Lst)/2) #增量++++++ times = 0 while gap > 0: for i in range(gap, len(Lst)): x = Lst[i] j = i while j > gap and Lst[j-gap] > x: Lst[j] = Lst[j-gap] j -= gap Lst[j] = x gap = int(gap /2) times += 1 print('Lst{}: {}'.format(times, Lst)) #在直接插入的基礎上增加增量,加一個迴圈,將其他兩重迴圈中的增量1改成增量gap #下面插入法採用的是元素交換法 def ShellInsertSort(Lst): gap = int(len(Lst)/2) #增量++++++ times = 0 while gap > 0: for i in range(gap, len(Lst)): x = Lst[i] j = i while j > gap and Lst[j-gap] > x: Lst[j], Lst[j-gap] = Lst[j-gap], Lst[j] j -= gap #Lst[j] = x gap = int(gap /2) times += 1 print('Lst{}: {}'.format(times, Lst)) Lst1 = [1,4,5,2,55,44,66,77,66,66,88,1] print(Lst1) ShellInsertSort(Lst1) print(Lst1) print('------------------------------------')