1. 程式人生 > >[python] 分治法實現歸併排序演算法

[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()

測試記錄:

注意事項:

進行輸入序列操作時,輸入的序列元素之間有且只能有一個空格隔開,並且在序列末尾不能含有空格,否則程式會報錯。