什么是归并排序
归并排序是利用归并技术进行的一种排序方法。所谓归并,是指将两个或者两个以上的有序表合并成一个新的有序表。归并技术经常应用在顺序表、链表等存储结构的合并算法中。
归并顺序的基本思想:将一个具有n个待排序记录的表看成是n个长度为1的有序子表,然后两两归并,得到[n/2]个长度为2的有序子表;再进行两两归并,得到[n/4]个长度为4的有序子表,如此重复,直至得到一个长度为n的有序表为止。
二路归并
最简单的归并排序就是将两个有序子表合并成一个有序表,我们把这种归并称为2路归并。类似的,还可以有k路归并。为了实现归并排序,下面先讨论如何实现2路归并
假设两个有序的子表存储在一维数组的相邻位置上,分别是r[low..mid],r[mid+1..high],先将其合并到临时数组r1中,待合并完成后再将r1复制会r[low..high]中。合并过程需要设置i,j和p3个指示器,其初值分别指向这3个记录区的起始位置,合并过程中,他们分别指示出3个记录区当前的操作位置。
合并时,依次比较r[i]和r[j],取较小的记录复制到r1[p]中,然后,将被复制的记录所对应的指示器i或者j加一,同时将指向复制位置的指示器也加一。重复这一过程,直至两个有序子表中有一个子表为空,若此时另一个子表尚有元素,则将其剩余记录依次复制r1中。
下列是代码实现:
template <typename T>
void Merge(int low, int mid, int high) {
T r1[N + 1];
int i = low, j = mid + 1, k = 0;
while (i <= mid && j <= high) {
if (r[i] <= r[j]) {
r1[k] = r[i];
i++;
k++;
} else {
r1[k] = r[j];
j++;
k++;
}
}
while (i <= mid) {
r1[k] = r[i];
i++;
k++;
}
while (j <= high) {
r1[k] = r[i];
j++;
k++;
}
for (k = 0, i = low; i <= high; ++i, k++)
r[i] = r1[k];
}
归并实现
采用分治策略,归并排序方法以2路归并为基础,用递归的形式描述。
(1)分解:将当前待排序表r[low..high]分为左右两个部分,分别称为左子表和右子表,即求得分裂点mid=[(low + high)/2]。
(2)求解:递归地对左右子表r[low..mid]和r[mid + 1..high]进行归并排序。
(3)组合:调用2路归并算法,将这两个已经有序的子表合成一个有序表。
因为一个记录总是自然有序的,所以递归的种植条件是子表的长度为1.具体的递归算法如下:
template<typename T>
void MergeSort(int low, int high) {
int mid;
if (low < high) {
mid = (low + high) / 2; //求得分裂点
MergeSort(low, mid); //递归处理左子表
MergeSort(mid + 1, high); //递归处理右子表
Merge(low, mid, high); //归并成一个有序表
}
}