歸併排序的主要思想是:分治(divide-and-conquer)策略,首先是分,先把問題拆分成規模很小的問題;然後是治,將子問題的答案合併成乙個更大的小問題的答案,直到合併成問題本身的答案。
分解的過程就是一顆二叉樹,既然是二叉樹,遞迴深度也就知道了是log2
再來看合併的過程,分別會有兩個指標指向兩個子串行的開頭。還會有乙個副本陣列暫存資料。有兩種情況:
1)如果兩個指標指向的元素都是子串行中的元素,那麼比較兩個元素,將較小元素放入副本陣列,後移對應指標。
2)如果只有乙個指標指向的元素還是子串行中的元素,那麼就將指標指向元素放入副本陣列,後移對應指標。
def
merge
(start,former,latter,end,src,des)
:#分治策略的治
gap = end -start +
1 i = start
j = latter
for step in
range
(gap):if
(i<=former)
and(j<=end)
:#兩個子串行都沒複製完,得判斷大小
if src[i]
<= src[j]
:# =保證演算法穩定
des[start+step]
= src[i]
#把前子串行元素複製到副本陣列
i +=
1#指標後移
else
: des[start+step]
= src[j]
#把後子串行元素複製到副本陣列
j +=
1#指標後移
elif
(i<=former)
:#前子串行還沒複製完
des[start+step]
= src[i]
i +=
1elif
(j<=end)
:#後子串行還沒複製完
des[start+step]
= src[j]
j +=
1#最後乙個迴圈必須有,因為每次治的時候都是以src的兩個子串行有序為前提
#des只是暫時放一下,因為歸併排序性質所以必須有乙個副本存在
for step in
range
(gap)
: src[start+step]
= des[start+step]
defmerge_sort
(start,end,src,des)
:#分治策略的分,既然是分,只需要start end,再看二者距離看可以分不
#如果可以分,就分開;不然就是遞迴終點
if start < end:
mid =
(start+end)//2
merge_sort(start,mid,src,des)
merge_sort(mid+
1,end,src,des)
merge(start,mid,mid+
1,end,src,des)
#當start>=end,遞迴終點,是乙個空殼函式,然後兩個空殼函式返回上一層
#執行上一層函式的最後一句merge,是對兩個長度為1的有序序列進行合併
defcopy_array
(arr)
:return
[none
for i in
range
(len
(arr))]
arr =[9
,8,4
,5,7
,1,3
,6,2
]temp = copy_array(arr)
#陣列副本
n =len
(arr)
merge_sort(
0,n-
1,arr,temp)
print
(arr)
重要的話都寫到注釋裡了。再提一下:
1)merge_sort函式代表「分」操作,是遞迴實現,遞迴終點是乙個空殼函式。因為是遞迴,所以是到了終點才能開始返回,所以就能實現將問題分解成最小規模的子問題後才開始合併子問題的答案。
會有兩種特殊情況,明顯需要特殊處理:
1)前子串行的最大值<=後子串行的最小值,直接返回
2)後子串行的最大值<=前子串行的最小值,雖然不能直接返回,但也需要特殊處理。就是先複製後子串行,再複製前子串行。
def
merge
(start,former,latter,end,src,des)
: gap = end -start +
1 i = start
j = latter
if src[former]
<= src[latter]
:#前子串行的最大值<=後子串行的最小值,直接返回
#print('第一種情況')
return
elif src[end]
<= src[start]
:#後子串行的最大值<=前子串行的最小值,也需要特殊處理
#print('第二種情況')
for step in
range
(gap)
:if j<=end:
des[start+step]
= src[j]
j +=
1elif i<=former:
des[start+step]
= src[i]
i +=
1else
:#正常的歸併操作
for step in
range
(gap):if
(i<=former)
and(j<=end)
:if src[i]
<= src[j]
:# =保證演算法穩定
des[start+step]
= src[i]
i +=
1else
: des[start+step]
= src[j]
j +=
1elif
(i<=former)
: des[start+step]
= src[i]
i +=
1elif
(j<=end)
: des[start+step]
= src[j]
j +=
1for step in
range
(gap)
: src[start+step]
= des[start+step]
defmerge_sort
(start,end,src,des)
:if start < end:
mid =
(start+end)//2
merge_sort(start,mid,src,des)
merge_sort(mid+
1,end,src,des)
merge(start,mid,mid+
1,end,src,des)
defcopy_array
(arr)
:return
[none
for i in
range
(len
(arr))]
arr =[1
,2,3
,4,7
,8,5
,6]result = copy_array(arr)
n =len
(arr)
merge_sort(
0,n-
1,arr,result)
print
(arr)
歸併演算法 歸併排序
歸併演算法 歸併排序 這周需要用到歸併演算法,於是找了找相關的資料,整理如下 歸併排序 merge sort 是利用 歸併 技術來進行排序。歸併是指將若干個已排序的子檔案合併成乙個有序的檔案。兩路歸併演算法 1 演算法基本思路 設兩個有序的子檔案 相當於輸入堆 放在同一向量中相鄰的位置上 r low...
歸併排序(2 路歸併排序)
遞迴寫法 include define maxn 100 void merge int a,int l1,int r1,int l2,int r2 將陣列a的區間 l1,r1 和區間 l2,r2 合併為乙個有序區間 else while i r1 while j r2 for int i 0 i非遞...
python歸併排序 python 歸併排序
排序思路 1.將陣列分成兩組a,b,建立臨時陣列 c,c長度 a b 2.i,j分別屬於a,b 3.若a i b j 將b j 放入c,j 否則 a i 放入c,i 4.迴圈3步驟,將a或b中剩餘的元素放入c,再將c複製到陣列中 5.遞迴3 4直到a,b序列的長度 1 歸併排序 class merg...