排序演算法之 歸併排序

2021-09-22 08:13:21 字數 1996 閱讀 3817

歸併排序(merge-sort)是利用歸併的思想實現的排序方法,該演算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞迴求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。在最壞、最佳、平均情況下歸併排序時間複雜度均為o(nlogn),從合併過程中可以看出歸併排序穩定。

分而治之

可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞迴去實現(也可採用迭代的方式去實現)。分階段可以理解為就是遞迴拆分子序列的過程,遞迴深度為log2n。

再來看看治階段,我們需要將兩個已經有序的子串行合併成乙個有序序列,比如上圖中的最後一次合併,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子串行,合併為最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。

# 獲取當前傳入的列表的長度

if n <=1:

# 如果列表長度為1,即已經拆分到最後一步了,就直接返回當前列表,不再往下繼續執行了

return alist

mid = n //

2# 取中間值,把當前輸入的列表從中間拆分

left_li = merge_sort(alist[

:mid]

)# 取左半部分

right_li = merge_sort(alist[mid:])

# 取右半部分

left_pointer =

0# 設定左半部分的指標,從0開始

right_pointer =

0# 設定右半部分的指標,從0開始

result =

# 定義乙個空列表result用於儲存每次遞迴產生的排好序的列表

while left_pointer <

len(left_li)

and right_pointer <

len(right_li)

:# 當各部分指標還沒走到末尾時

if left_li[left_pointer]

<= right_li[right_pointer]

:# 把較小的值存入result並讓相應的指標+1

) left_pointer +=

1else:)

right_pointer +=

1 result += left_li[left_pointer:

]# 如果是奇數個元素,別忘了把最後單個的元素也新增到result裡

result += right_li[right_pointer:

]return result # 最終返回的是乙個新的排好序的列表result,因此空間複雜度要多一倍

可以說歸併排序是比較複雜的排序,特別是對於不了解分治法基本思想的同學來說可能難以理解。總時間=分解時間+解決問題時間+合併時間。分解時間就是把乙個待排序序列分解成兩序列,時間為一常數,時間複雜度o(1).解決問題時間是兩個遞迴式,把乙個規模為n的問題分成兩個規模分別為n/2的子問題,時間為2t(n/2).合併時間複雜度為o(n).總時間t(n)=2t(n/2)+o(n).這個遞迴式可以用遞迴樹來解,其解是o(nlogn).此外在最壞、最佳、平均情況下歸併排序時間複雜度均為o(nlogn).從合併過程中可以看出合併排序穩定.用遞迴樹的方法解遞迴式t(n)=2t(n/2)+o(n):假設解決最後的子問題用時為常數c,則對於n個待排序記錄來說整個問題的規模為cn。

排序演算法之歸併排序

歸併排序也是經典的使用分治法思想的代表演算法之一。歸併排序的效率很高,而且是一種穩定的排序。其總體的思想思路就是將待排序的元素分成大致相同的兩個子集合,分別對兩個子集合進行排序,最終將排序的子集合合併成排好序的總集合 歸併排序c 實現如下 include void mergesort int arr...

排序演算法之歸併排序

歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用,歸併排序將兩個已排序的表合併成乙個表。歸併排序基本原理 通過對若干個有序結點序列的歸併來實現排序。所謂歸併是指將若干個已排好序的部分合併成乙個有序的部分。歸併排序基本思...

排序演算法之歸併排序

歸併排序,和快排一樣同樣採用了分治的思想,將兩個 或以上 有序表合併成乙個新的有序表。歸併排序步驟如下 把n個記錄看成 n個長度為 1 的有序子表 進行兩兩歸併使記錄關鍵字有序,得到 n 2 個長度為 2 的有序子表 重複第2步直到所有記錄歸併成乙個長度為n的有序表為止。下面是歸併排序演算法的遞迴實...