我们可以使用的算法设计技术有很多。插入排序用的是增量方法,即在已经排好的数组中不断加入新的元素。下面考虑一种被称为“分治法”的设计方法。
2.3.1分治法
分治法的思想:将原问题分解为几个规模较小但是类似于原问题的子问题,递归地求解这些子问题,然后合并这些子问题的解来建立原问题的解。分治模式在每层递归时有三个步骤:
分解原问题为若干子问题;
解决这些子问题,递归地求解各子问题,若子问题规模足够小,则直接求解;
合并这些子问题的解成原问题的解。
归并排序算法完全遵循分治模式,操作如下:
分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列;
解决:使用归并排序递归地排序两个子序列;
合并:合并已经排序的子序列以产生已排序的答案。
当被排序的序列长度为1时,递归“开始回升”。
下面写出合并这一步的伪代码,时间复杂度为theta(n).
//MERGE 伪代码 n1 = q - p + 1 n2 = r - q Let L[1..n1+1] and R[1..n2+1] be new arrays for i = 1 to n1 L[i] = A[p + i -1] for j = 1 to n2 R[i] = A[q+j] L[n1 + 1] = ∞ R[n2 + 1] = ∞ i = 1 j = 1 for k = p to r if L[i] <= R[j] A[k] = L[i] i = i + 1 else A[k] = R[j] j = j + 1
注意点:
1、从左右两个序列中依次取出最小的数存入原数组中;
2、左右两个子序列分别递增,在哪一个子列选出一个数,这个序列下标加1;
3、为了不用每次确认子序列是否为空,要在子序列的最后放一张“哨兵牌”,这张牌非常大,当碰到这张牌时,一定是另一个序列的数被选出,当两个子序列都到达“哨兵牌”时,此时恰好所有数都存进原数组了(由循环头的迭代数目控制);在左右序列的长度不一致时,哨兵牌才会发挥威力,两个子序列长度一样的时候,同时达到最后一张牌,那么“哨兵牌”就没什么作用了;
4、另外注意的是,需要开辟新的数组来存储每个子序列,注意下标的确认,尤其是计算子序列长度时不要弄错。
时间: 2024-11-06 03:35:05