排序算法总结之——归并排序

定义

归并就是将两个或多个有序的序列合并成一个有序序列的过程。

二路归并排序是面试中考查最多的排序算法之一。

归并排序有两种:
1、一般归并排序,空间复杂度O(n)
2、原地归并排序,空间复杂度O(1)


一般归并排序

基本思想:将两个或者两个以上的有序表合成一个新的有序表。
归并排序无论是顺序存储还是链式存储结构都有较好的性能。

时间复杂度:O(nlogn)
空间复杂度:O(n)
是否稳定:是

举例说明:对序列{49,38,65,97,76,13,27}共七个元素的无序序列进行归并排序。
其过程如下所示:

  • 初始状态:[49] [38] [65] [97] [76] [13] [27] ——>相邻两个数分为一组,归并,则得到
  • 一趟归并:[49, 38] [65, 97] [13, 46] [27] ——>相邻两组分为一组,归并
  • 二趟归并:[38, 49, 65, 97] [13, 27, 46] ——>相邻两组分为一组,归并
  • 三趟归并:[13, 27, 38, 49, 65, 76, 97] ——>完成

从上面的分析,容易看出,归并排序是个递归的过程。递归过程的有两步:分割 和 合并。
由此可以写出以下代码:

void mSort(int Record[], int temp[], int begin, int end)
{
    if(begin < end)
    {
        int mid = (begin + end)/2;
        mSort(Record, temp, begin, mid);
        mSort(Record, temp, mid+1, end);
        merge(Record, temp, begin, mid, end);
    }
}

分析:这段代码很简单,共三个步骤:
1、将左半部分分割;
2、将有半部分分割;
3、将左右两半合并;
其中,temp是和Record一样大小的辅助数组。

下面来看下 合并操作。
合并两个有序序列p , q的过程很简单,直接看代码:
(注意:需要使用p.length + q.length的辅助空间)

void merge(int Record[], int temp[], int begin, int mid, int end)
{
    int lBegin = begin, lEnd = mid, rBegin = mid+1, rEnd = end;
    int k = begin;

    while(lBegin <= lEnd && rBegin <= rEnd)
    {
        if(Record[lBegin] <= Record[rBegin])
            temp[k++] = Record[lBegin++];
        else
            temp[k++] = Record[rBegin++];
    }

    while(lBegin <= lEnd)
        temp[k++] = Record[lBegin++];

    while(rBegin <= rEnd)
        temp[k++] = Record[rBegin++];

    while(begin <= end)
    {
        Record[begin] = temp[begin];
        begin++;
    }
}

以上就是一般归并排序的核心过程。

完整代码:

//合并子函数
void merge(int Record[], int temp[], int begin, int mid, int end)
{
    int lBegin = begin, lEnd = mid, rBegin = mid+1, rEnd = end;
    int k = begin;

    while(lBegin <= lEnd && rBegin <= rEnd)
    {
        if(Record[lBegin] <= Record[rBegin])
            temp[k++] = Record[lBegin++];
        else
            temp[k++] = Record[rBegin++];
    }

    while(lBegin <= lEnd)
        temp[k++] = Record[lBegin++];

    while(rBegin <= rEnd)
        temp[k++] = Record[rBegin++];

    while(begin <= end)
    {
        Record[begin] = temp[begin];
        begin++;
    }
}
//分割子函数
void mSort(int Record[], int temp[], int begin, int end)
{
    if(begin < end)
    {
        int mid = (begin + end)/2;
        mSort(Record, temp, begin, mid);
        mSort(Record, temp, mid+1, end);
        merge(Record, temp, begin, mid, end);
    }
}
//归并排序
void mergeSort(int Record[], int length)
{
    if(Record == NULL || length <= 0)
        return;
    int *temp = new int[length];
    mSort(Record, temp, 0, length-1);
    delete[] temp;
}

参考资料:
1、www.tobebatman.com
2、数据结构,严蔚敏版

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值