文章同步发布于博客
从头开始复习算法有一段时间了,有输入也要有输出。除了交编程作业以外,也要整理自己的笔记。
归并排序,使用分治的思想,将原问题折半分解为子问题,再使用同样的算法解决子问题。
总体思路
如果数组长度为 1,就返回该数组。
如果不是 1,则将数组折半,对每一半执行归并排序,将排好序的数组存在两个变量里。
之后,通过归并算法将两个数组拼合成一个排好序的数组。
返回该排好序的数组。
递归过程中,数组会被逐层拆分,直到每一个子问题都变为长度为一的数组,此时,每一个子问题的数组都是排好序的了(因为就一个元素),就会触发拼合操作。
将两个已排好序的数组拼合的过程如下:
创建一个长度为两数组长度之和的空数组。
比较两个数组的头元素,将小的那个移至新数组非空部分的末尾。循环执行直至其中一个数组的元素全部被挪走。
将剩余的部分按序挪至新数组的末尾。
这样就得到了一个合并之后的排好序的数组。
再逐层递归执行合并操作,直到最后将原数组排好序。
伪代码:
MergeSort(A[1...n])
if n == 1:
return A
m = floor(n/2)
B = MergeSort(A[0...m])
C = MergeSort(A[m+1...n])
A' = Merge(B, C)
return A'
Merge(B[1...p], C[1...q])
// B and C are sorted
D = empty array of size p+q
while B and C are both not empty:
b = B[0]
c = C[0]
if b <= c:
move b to the end of D
else:
move c to the end of D
// after the while loop, one of the two array is now empty
move the rest of B or C to the end of D
return D
复制代码
Python 3 实现:
可以存储至本地文件然后运行查看结果
def MergeSort(A):
if len(A) == 1:
return A
m = len(A) // 2
B = MergeSort(A[0:m])
C = MergeSort(A[m:len(A)])
A_new = Merge(B, C)
return A_new
def Merge(B, C):
D = [None] * (len(B)+len(C))
i = 0
j = 0
while i < len(B) and j < len(C):
b = B[i]
c = C[j]
if b <= c:
D[i+j] = b
i += 1
else:
D[i+j] = c
j += 1
while i < len(B):
D[i+j] = B[i]
i += 1
while j < len(C):
D[i+j] = C[j]
j += 1
return D
if __name__ == '__main__':
a = [1, 3, 7, 2, 9, 6, 8, 10, 1, 2, 5]
sorted_A = MergeSort(a)
print(sorted_A)
复制代码
JavaScript 实现
同样可以保存文件,然后通过 node 命令运行
function mergeSort(array){
if (array.length === 1)
return array
let m = Math.floor(array.length / 2)
let B = mergeSort(array.slice(0, m))
let C = mergeSort(array.slice(m, array.length))
let A_sorted = merge(B, C)
return A_sorted;
}
function merge(B, C){
let i = 0
let j = 0
let D = []
while(i < B.length && j < C.length){
if (B[i] <= C[j]){
D.push(B[i++])
} else {
D.push(C[j++])
}
}
while (i < B.length) D.push(B[i++])
while (j < C.length) D.push(C[j++])
return D
}
let a = mergeSort([1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]);
console.log(a)
复制代码