[python] 分治法實現歸併排序演算法
分治法實現歸併排序
分治法簡介:
分治法從字面上的解釋是“分而治之”,就是把一個複雜的問題分成兩個或者更多相同或者相似的子問題,再把子問題分成更小的子問題,直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。歸併排序演算法也是簡歷在分治法的操作上實現的演算法,歸併排序將一個序列分成多個子序列,將所有子序列有序,再將有序的子序列合併,得到排好序的序列。
歸併排序基本原理:
(1) 遞迴將問題分解,將序列元素大於等於3個的時候,將陣列分為兩個更小的陣列並繼續判斷元素個數進行劃分。
(2) 解決小規模的問題,如序列中只有一個或者兩個元素的時候,將小規模問題進行排序。
(3) 依次將小規模的問題進行合併,每次得到比小規模問題大一倍的規模的有序序列。
(4) 最後規模擴大到原問題的規模時,得到的序列便是排好序的有序序列。
歸併排序關鍵程式碼思想:
(1) 歸併過程的實現,定義一個歸併函式並且傳入三個引數,傳入序列,左端點下標和右端點下標。對序列進行平均劃分,將兩個序列中較小元素的值先進行比較存放到一個臨時序列,再將未比較的值進行依次傳入臨時序列,最後將臨時列表重新賦給傳入引數列表。
(2) 分治操作實現,定義一個分治函式,傳入三個引數,傳入序列,左端點以及右端點下標。對序列長度進行判斷,如果序列長度大於等於1時,繼續進行劃分,如果序列長度小於1,就停止劃分,最後再實現由區域性到整體的合併。
(3) python3.6版本中的輸入預設為字串,因此輸入序列採用split()函式對輸入的字串以“ ”為界進行分離取值,再將其存放到一個數組中。注意存放到陣列中時,每個元素都還是字串,利用強制轉換將每個元素轉換為int型,再將其append到陣列中。
(4) 計算程式執行時間,匯入python自帶的time模組,採用模組中的clock函式,在歸併排序前後分別呼叫clock函式記錄時間,最後兩個時間值作差值,得到歸併排序演算法實現的執行時間。
歸併具體例項分析:
假如給定序列5 3 4 6 8 1 7 9,利用上述思想對序列進行排序。
(1)先將序列進行劃分為細小的模組
首先原始數列傳入:5 3 4 6 8 1 7 9,第一組合並還未進行。
第一次劃分:5 3 4 6 || 8 1 7 9,第二組合並還未進行。
第二次劃分:5 3 || 4 6 || 8 1 || 7 9,第三組合並還未進行。
(2) 因為每組元素序列個數已經小於等於2,因此開始進行合併操作
進行第三組合並:5 3 || 4 6 || 8 1 || 7 9 ——> 3 5 || 4 6 || 1 8 || 7 9
進行第二組合並:3 5 4 6 || 1 8 7 9 ——> 3 4 5 6 || 1 7 8 9
進行第一組合並: 3 4 5 6 || 1 7 8 9 ——> 1 3 4 5 6 7 8 9
最終得到的序列便為已經排好序的有序序列。
歸併排序程式碼的具體實現:
import time
def hebin(arr,left,right):
mid = int((right - left)/2 + left)
temp = []
i = left
j = mid + 1
while i<mid+1 and j<right+1:
if arr[i]>arr[j]:
temp.append(arr[j])
j+=1
else:
temp.append(arr[i])
i+=1
while i<mid+1:
temp.append(arr[i])
i+=1
while j<right+1:
temp.append(arr[j])
j+=1
mm = 0
for tt in range(left,right+1):
arr[tt] = temp[mm]
mm+=1
def fenzhi(arr,left,right):
if right - left<1:
return 0
else:
mid = int((right - left)/2 + left)
fenzhi(arr,left,mid)
fenzhi(arr,mid+1,right)
hebin(arr,left,right)
def main():
a=[]
t = input().split(" ")
time1 = time.clock()
for tt in t:
a.append(int(tt))
left = 0
right = len(a) - 1
fenzhi(a,left,right)
time2 = time.clock()
for n in a:
print(n ,end = " ")
print("\n程式執行時間:%f"%(time2 - time1))
if __name__ == '__main__':
main()
測試記錄:
注意事項:
進行輸入序列操作時,輸入的序列元素之間有且只能有一個空格隔開,並且在序列末尾不能含有空格,否則程式會報錯。