歸併排序
用下邊例子來
level 0 8 6 2 3 1 5 7 4
leve 1 8 6 2 3 1 5 7 4
leve 2 8 6 2 3 1 5 7 4
leve 3 8 6 2 3 1 5 7 4
先將這組數分組,每次在中間分開,知道分成單個數位爲止,然後歸併。
從第三層爲第二層歸併
leve 2 6 8 2 3 1 5 4 7 這樣就分出來四個有序的序列
再到leve1 層
leve 1 2 3 6 8 1 4 5 7 形成兩個有序的序列
再到leve0
leve0 1 2 3 4 5 6 7 8
就得出了想要的結果。
圖解:
代碼:
a=[8, 2, 6, 3, 7, 2, 8, 5, 5, 5, 3, 8, 3, 4, 4]
def merge(arr, l, mid, r):
aux=[]
for c in range(l,r+1):
aux.append(arr[c])
i=l
j=mid+1
for k in range(l,r+1):
if i > mid:
arr[k] = aux[j - l]
j+=1
elif j > r:
arr[k] = aux[i - l]
i+= 1
elif aux[i-l] <= aux[j-l]:
arr[k]=aux[i-l]
i+=1
else:
arr[k] = aux[j-l]
j+=1
return arr
def mergeSort1(arr,l,r):
if l>=r:
return None
mid = (l+r)/2
mergeSort1(arr, l, mid)
mergeSort1(arr, mid+1, r)
merge(arr, l, mid, r)
return arr
def mergeSort(arr):
arr=mergeSort1(arr,0,len(arr)-1)
return arr
print mergeSort(a)
其中mege可以修改爲下邊
def merge(arr,l,mid,r):
ar=[]
lt=l
rt=mid+1
while lt <= mid and rt <= r:
if arr[lt] < arr[rt]:
ar.append(arr[lt])
lt+=1
else:
ar.append(arr[rt])
rt+=1
if rt <= r:
ar.extend(arr[rt:r+1])
if lt <= mid:
ar.extend(arr[lt:mid + 1])
arr[l:r+1]=ar
return arr
不再原地修改,直接將新生成的空間返回:
def merge(left,right):
ar=[]
mid =len(left)-1
r = len(right)-1
lt=0
rt=0
while lt <= mid and rt <= r:
if left[lt] < right[rt]:
ar.append(left[lt])
lt+=1
else:
ar.append(right[rt])
rt+=1
if rt <= r:
ar.extend(right[rt:r+1])
if lt <= mid:
ar.extend(left[lt:mid + 1])
return ar
def mergeSort(arr):
l=0
r=len(arr)-1
if l >=r:
return arr
mid = (r+l)//2
left = mergeSort(arr[l:mid+1])
right = mergeSort(arr[mid+1:r+1])
arr = merge(left,right)
return arr
a=[1,3,5,3,6,7,8]
print(mergeSort(a))
歸併排序當右邊的第一個元素大於左邊的最後一個元素,可以直接合並,提前中止,修改代碼如下:
def merge(left,right):
ar=[]
mid =len(left)-1
r = len(right)-1
lt=0
rt=0
while lt <= mid and rt <= r and left[mid] > right[rt]:
if left[lt] < right[rt]:
ar.append(left[lt])
lt+=1
else:
ar.append(right[rt])
rt+=1
if lt <= mid:
ar.extend(left[lt:mid + 1])
if rt <= r:
ar.extend(right[rt:r + 1])
return ar
參考文獻: