排序算法4之归并排序

归并排序

归并排序是建立在归并操作上的一种排序算法,该算法采用分治的思想(divide and conquer)。就是先将序列进行分裂成一个个子序列,使得每个子序列都是有序的,然后再将所有的子序列整合成一个完整的序列。所以整个算法分为两部分,分裂和合并。分裂比较简单,最容易想到的就是折半分解,直至每个子序列是一个单独的数为止。合并就可能麻烦一点。

合并
假设存在两个已经排列好的子序列 {a1,a2,a3an} {b1,b2,b3bm} 。我们逐个比较两个子序列中项目的大小,将关键字较小的项目放入一个临时数组中,然后从对应的子序列删除放入的项目,当某个子序列为空时,就可以将另外一个子序列的全部项目依次放入临时数组中。然后利用临时数组给 {c1,c2,c3cn+m} 赋值。

void MemeryArray(int* p,int first,int middle,int end,int* tmp)
{
    int i=first;//第一个子序列的起始位置
    int m=middle;//第一个子序列的终止位置
    int j=middle+1;//第二个子序列的起始位置
    int n=end;//第二个子序列的终止位置
    int k=0;
    while(i<=m&&j<=n)
    {
        if(p[i]<p[j])
            tmp[k++]=p[i++];
        else
            tmp[k++]=p[j++];
    }//将较小的项目放入临时数组tmp
    while(i<=m)
        tmp[k++]=p[i++];
    while(j<=n)
        tmp[k++]=p[j++];//将剩余的某一子序列全部放入临时数组
    for(int i=0;i<k;i++)//利用临时数组对原本的序列进行赋值
        p[first+i]=tmp[i];
}

这里写图片描述
上图可以很直接的说明归并排序的思想,下面是完整的归并排序的code

#include<iostream>
using namespace std;
void MemeryArray(int* p,int first,int middle,int end,int* tmp)
{
    int i=first;
    int m=middle;
    int j=middle+1;
    int n=end;
    int k=0;
    while(i<=m&&j<=n)
    {
        if(p[i]<p[j])
            tmp[k++]=p[i++];
        else
            tmp[k++]=p[j++];
    }
    while(i<=m)
        tmp[k++]=p[i++];
    while(j<=n)
        tmp[k++]=p[j++];
    for(int i=0;i<k;i++)
        p[first+i]=tmp[i];
}//合并操作

void mergeSort(int* p,int first,int end,int* tmp)
{
    if(first<end)//递归操作的终止条件就是first>=end
    {
        int middle=(first+end)/2;
        mergeSort(p,first,middle,tmp);//分解
        mergeSort(p,middle+1,end,tmp);//分解
        MemeryArray(p,first,middle,end,tmp);//合并
    }
}
bool MergeSort(int* p,int length)
{
    int* q=new int[length];//由于每次调用归并排序都需要一个临时数组,为了避免麻烦,我们直接创建一个较大的临时数组,供所有的归并排序使用。
    if(q==NULL)
        return false;
    mergeSort(p,0,length-1,q);
    delete[] q;
    return true;
}
int main()
{
    int data[5]={5,4,3,2,1};
    MergeSort(data,sizeof(data)/sizeof(data[0]));
    for(int i=0;i<sizeof(data)/sizeof(data[0]);i++)
        cout<<data[i]<<endl;
    return 0;

}

从上面可以分析出来,归并排序的总共会递归调用 log2(length) 次,而每次调用的主要时间代价就是合并,从合并函数我们知道,每次的需要赋值 2length 次,所以时间复杂度 Ω(nlog(n)) ;空间复杂度,由于需要额外开辟一个临时数组,所以空间复杂度仍然是 Ω(n) ;同时归并排序是一种稳定排序。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值