歸併排序(Merge Sort)

2021-09-24 10:19:37 字數 3184 閱讀 6431

歸併排序(merge sort)

平均時間複雜度: o(n

logn

)o( n log n)

o(nlog

n)空間複雜度: o(n

)o(n)

o(n)

穩定性:穩定

基本形式:

歸併排序是建立在歸併操作上的一種有效的排序演算法,將已有序的子串行合併,得到完全有序的序列,是分治演算法的典型應用。常用的將兩個有序序列合併成乙個有序序列的演算法稱為二路歸併。

如何使子串行有序?

要將有序的子串行進行合併,首先要得到有序的子串行。這就是分治演算法的「分」的過程。先將完全序列中的每乙個數都分為乙個子串行,也就是每乙個子串行中只有乙個數,本身即是有序,就可以開始合併操作了。這是從上到下的過程,就形成了一棵樹。

如何合併?

這就是分治演算法中的「治」。對於兩個有序的子串行,我們將其合併即可,這樣就需要額外的儲存空間。這個o(n

)o(n)

o(n)

的額外儲存空間可以事先申請好,也可以使用的時候用多少申請多少。

為什麼歸併排序在最好情況和最壞情況下的時間複雜度都是o(n

logn

)o(n log n)

o(nlog

n)?因為歸併排序,先要「分」,這個過程就構成一棵樹,以二路歸併為例,n個數的序列要分成n個有序子串行要分成 log

2n

log_2n

log2​n

層(樹的深度),在」治「的過程中,每一層的平均時間複雜度為o(n

)o(n)

o(n)

,故整體的平均時間複雜度為nlo

g(n)

n log(n)

nlog(n

)。不管原始序列是否有序,故按照這個步驟進行操作,時間複雜度都是一樣的。

實現遞迴

def

merge_sort

(array):if

len(array)

<=1:

return array

middle =

len(array)//2

array1 = merge_sort(array[

:middle]

) array2 = merge_sort(array[middle:])

result =

i,j =0,

0while

(i <

len(array1)

and j <

len(array2)):

#注意這裡是小於等於,保證穩定性

if array1[i]

<= array2[j]:)

i +=

1else:)

j +=

1 result += array1[i:

]+ array2[j:

]return result

迭代

迭代的思想也是分組排序,然後合併, 我們用乙個視窗,視窗的長度從2到(le

n(ar

ray)

)+1/

/2

(len(array))+1//2

(len(a

rray

))+1

//2, 在每個視窗內都需要額外的空間輔助排序。**總體分為兩個部分,merge 函式用來合併有序數組成新的更長的有序陣列,主函式用來用視窗掃瞄陣列然後呼叫merge函式合併陣列。

def

merge_sort

(array)

:def

merge

(array, low, middle, high)

:# 用middle 指標將low和high的陣列分成兩個陣列 left array[low: middle] right array[middle: high]

low_array = array[low: middle]

high_array = array[middle:high+1]

low_idx, high_idx, array_idx =0,

0, low

while

(low_idx <

len(low_array)

and high_idx <

len(high_array)):

if low_array[low_idx]

<= high_array[high_idx]

: array[array_idx]

= low_array[low_idx]

low_idx +=

1else

: array[array_idx]

= high_array[high_idx]

high_idx +=

1 array_idx +=

1 array[array_idx:high+1]

= low_array[low_idx:

]+ high_array[high_idx:

]

step =

1while step <

(len

(array)):

low =

0while

(low <

len(array)):

middle = low + step

high =

min(low + step *2-

1,len(array)-1

)if middle <= high:

merge(array, low, middle, high)

low += step*

2 step *=

2return array

這裡一定要用middle指標,不能用low 和 high除以2,因為在邊界的時候可能不能均分成兩個陣列(比如長度6,分成了左四右二的有序陣列)

改進如果子陣列較小(7左右),則採用速度更快的插入排序。這樣做,會帶來一定的好處,例如歸併排序減少分配、**臨時儲存區域的頻次,快速排序減少遞迴層次等。

檢測待歸併的兩個子陣列是否已經有序,如果已經有序則直接複製該子陣列;

特殊情況的處理,比如當前的兩個子串行中,左邊的最大值小於右邊的最小值,可以直接返回;或者嘴邊的最小值大於右邊的最大值,左右互換即可。

歸併排序 Merge sort

merge the a s.m and a m 1.t to r s.t template void two merge typet a,typet r,int s,int m,int t while i m r k a i while j t r k a j merge the a 0.n 1 s...

歸併排序(merge sort)

歸併排序 歸併排序是一種遞迴排序演算法,無論陣列元素的原始順序如何,其效能恆定不變。將陣列一分為二,分別排序兩部分元素,再將有序的兩半陣列歸併為乙個有序陣列。歸併步驟比較陣列前一半的元素與陣列的後一半元素,並將較小元素移到臨時陣列,該過程繼續前進,直到其中一半再沒有元素為止。此後只需將其餘元素移到臨...

歸併排序 Merge Sort

歸併排序 merge sort 是利用 歸併 技術來進行排序。歸併是指將若干個已排序的子檔案合併成乙個有序的檔案。兩路歸併演算法 1 演算法基本思路 設兩個有序的子檔案 相當於輸入堆 放在同一向量中相鄰的位置上 r low.m r m 1.high 先將它們合併到乙個區域性的暫存向量r1 相當於輸出...