資料結構之內部排序--希爾排序
阿新 • • 發佈:2018-11-13
概要
-IDE:Pycharm
-Python版本:python3.x
-演算法分類:內部排序->插入類排序->希爾排序
演算法思想
希爾排序又稱縮小增量排序法,是一種基於插入思想的排序方法。它利用了直接插入排序的最佳性質,首先,將待排序的關鍵字序列分成若干個較小的序列,對子序列進行直接的插入排序,使整個待排序列排好序。
過程如下:
1.首先選定記錄間的距離$d_i(i=1)$,在整個待排序記錄序列中將所有間隔為$d_1$的記錄分成一組,進行組內直接插入排序。
2.然後選取$i=i+1$,記錄間的距離為$d_i(d_i<d_i-_1)$,在整個待排序記錄序列中,將所有間隔為$d_i$的記錄分成一組,進行組內直接插入排序。
3.重複步驟2直至記錄間的距離$d_i=1$,此時整個只有一個子序列,對該序列進行直接插入排序,完成整個排序過程。
演算法要點
增量取法
關於增量$d$的取法,最初希爾提出取$d=[n/2]$,再取$d=[d/2]$,直到$d=1$為止。該思路的缺點是,奇數位置的元素在最後一步才會與偶數位元素進行比較,使得排序效率低。後來Knuth提出$d=[d/3]+1$。此外還有多種取法,但無法證明那種最優。
逆轉數
為了分析希爾排序的優越性,這裡引入逆轉數的概念。對於待排序列中的某個記錄的關鍵字,它的逆轉數是指在它之前比此關鍵字大的關鍵字個數。
假設:被調換位置的兩個關鍵字之間有$l$個介於兩個關鍵字之間的數。逆轉數之和一定會減小$2l+1$
當逆轉數為$0$時則表明整個排序完成。
穩定性與時間複雜度
排序演算法 | 穩定性 | 時間複雜度 | 最好情況 | 最壞情況 | 空間複雜度 |
---|---|---|---|---|---|
希爾排序 | 不穩定 | $O(n^{1.5})$ | $O(1)$ |
Python程式碼清單
# !/usr/bin/python3 # _*_ coding:utf-8 _*_ # 希爾排序 import random, time, sys def SS(number,maxNumber): # 生成隨機數 timeStart = time.time() listA = [0] # 0位 一般都空出來,防止out of index 或者做監視哨或者備份某個值。 for i in range(number): listA.append(random.randint(0, maxNumber)) # 新增生成的值。 timeEnd = time.time() timeIs = timeEnd - timeStart listD = [0, int(number/2)] # listD用於存放增量d,第0位用0佔位,我們從第一位開始迴圈。 while True: if listD[-1] != 1: # 判斷最後一個元素(增量)是否是1,若不是繼續計算增量。 listD.append(int(listD[-1]/3)+1) # 計算增量 else: break # 若是1,則退出迴圈。 print('生成%d個數的時間是%f' % (number, timeIs)) # print(listA[1:]) # 從第一位開始輸出。0位不顯示。 # print(listD[1:]) # 輸出d的增量的列表 #################################################### # 希爾排序演算法。 我認為 右邊是前,左邊是後。 timeStart = time.time() # 開始記錄時間 # 演算法開始 for d in listD[1:]: # 設定迴圈的次數,與d有關係。 base = 1 + d # 從前向後找,從哦能通過d+1位開始。 for item in range(base, len(listA)): # 每次增加一位 if listA[item] < listA[item-d]: # 如果遇到前面小,後面大的數, listA[0] = listA[item] # 複製前面的數 aim = item-d # 選定目標的位置。 while True: # 開始迴圈查詢序列。 if aim > 0 and listA[0] < listA[aim]: # 這裡應設定條件,以防無限迴圈。 listA[aim + d] = listA[aim] # 將選定目標位的數後移。 aim = aim - d # 每次向前查詢,步長為d else: break # 條件不符合 break 出 listA[aim+d] = listA[0] # 把目標值放入目標位。加d是因為在迴圈時多減了d。 # 演算法結束 timeEnd = time.time() # 記錄結束時間。 timeIs = timeEnd - timeStart # 排序花費的時間 print('排序%d個數,花費的時間是%f' % (number, timeIs)) # print(listA[1:]) # 列印最後排序的列表。 if __name__ == '__main__': helpInfo = ''' This program is for Shell's Sort. How to use it! Follow the example! python Shell's_Sort.py 10 100 The 10 representative will generate ten numbers. 100 representative the max-number you make. ''' command = sys.argv[0:] # 獲取從鍵盤輸入的值。 if len(command) != 3 or 'help' in command: # 判斷是否合法,或包含help print(helpInfo) # 列印幫助文字。 else: try: # 嘗試將輸入轉化為整數。 number = int(command[1]) maxNumber = int(command[2]) except ValueError: # 數值型錯誤。 print(helpInfo) # 列印幫助。 sys.exit(1) # 退出程式。 SS(number, maxNumber) # 一切完好,呼叫函式。
有什麼問題請聯絡我
QQ:3116316431 (請附上資訊)
E-mail:[email protected]