设计算法
我们可以选择使用的算法设计方法有很多,插入排序使用了增量方法:在排序子数组A[1…j-1]后,将单个元素A[ j ]插入子数组的适当位置,产生排序好的子数组A[1…j]。
而这次我们将考查另一种称为“分治法”的设计方法。
分治法
分治法的思想:将原问题分解为几个规模较小的但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来解决原问题的解。
分治模式在每层递归时都有三个步骤:
分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
解决这些子问题,递归地求解各子问题。然而,若子问题的规模足够小,则直接求解。
合并这些子问题的解成原问题的解。
归并排序算法完全遵循分治模式。直观上其操作如下:
分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。
解决:使用归并排序递归地排序两个子序列。
合并:合并两个已排序的子序列以产生已排序的答案。
当待排序的序列长度为1时,递归“开始回升”,在这种情况下不用做任何工作,因为长度为1的每个序列都已经排好序。归并排序算法的关键操作是“合并”步骤中两个已排序序列的合并。
我们用算法中常用的伪代码来表示“合并”步骤中两个已排序序列的合并:
MERGE(A, p, q, r) #伪代码解读,定义MERGE函数,用于合并两个排序好的序列
n1= q - p +1 #确定两段序列的长度n1,n2
n2= r - q
let L[1..n1+1] and R[1..n2+1] be new arrays #申请两段新的数组L,R,长度分别为n1+1,n2+1
for i = 1 to n1
L[i]= A[p+i-1] #将需要合并的第一段序列A[p...p+n1-1]]赋值给L
for j = 1 to n2
R[j] = A[q + j] #将需要合并的第二段序列A[q...q+n2]赋值给R
L[n1 + 1] = ∞
R[n2 +1] = ∞ #给予两端序列底部标记,标记其到达底部
i = 1
j = 1 # 重置 i,j,使i,j指向L,R的第一个元素
for k = p to r #开始合并,比较大小,当L[i]小于等于R[j],A[k]取L[i],i之后指向L中下一个元素
if L[i]<=R[j] #k是指要排序的序列的下标,每次循环迭代确定A[k]的值,之后k=k+1,确定下个元素
A[k] = L[i]
i = i + 1
else #当L[i]不小于等于R[j]时,A[k]取R[j],j之后指向R中的下一个元素
A[k] = R[j]
j = j + 1
Python对归并排序的实现:
#归并算法:算法设计中分治法的体现
def Merge(A, p, q, r):
n1