【排序算法】之归并排序

什么是归并排序

归并排序是利用归并技术进行的一种排序方法。所谓归并,是指将两个或者两个以上的有序表合并成一个新的有序表。归并技术经常应用在顺序表、链表等存储结构的合并算法中。

归并顺序的基本思想:将一个具有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);      //归并成一个有序表
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值