无聊时总结总结算法之06归并排序

9 篇文章 0 订阅
1 篇文章 0 订阅

归并排序

1、基本思想
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
归并排序示例:
这里写图片描述
2、算法时间复杂度
最好的情况下:一趟归并需要n次,总共需要logN次,因此为O(N*logN)
最坏的情况下,接近于平均情况下,为O(N*logN)
说明:对长度为n的文件,需进行logN 趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
3、稳定性
归并排序最大的特色就是它是一种稳定的排序算法。归并过程中是不会改变元素的相对位置的。
4、缺点是,它需要O(n)的额外空间。但是很适合于多链表排序。

/*
合并方法:
设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。
1.j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标

2.若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束

3.选取r[i]和r[j]较小的存入辅助数组rf
  如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵
  否则,rf[k]=r[j]; j++; k++; 转⑵

4.将尚未处理完的子表中元素存入rf
  如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空
  如果j<=n ,  将r[j…n] 存入rf[k…n] //后一子表非空

5.合并结束。
*/
void Merge(int* yuan,int* fu,int i, int m, int n)
{
    int j = m+1;
    int k = i;
    for(;i<=m && j<=n;++k)
        {
            if(yuan[j] < yuan[i])
                    fu[k] = yuan[j++];
            else
                    fu[k] = yuan[i++];


        }
    while(i <= m)  fu[k++] = yuan[i++];  //上边没排完
    while(j <= n)  fu[k++] = yuan[j++];


}
void MergeSort(int* yuan , int* fu ,int length)
{
    int len =1;//子表长度
    int* q = yuan ;
    int* tmp ;

    while(len<length)
    {
        int m = len; //记录中间元素
        len = 2*m; //子表是成倍的,余下再说
        int i=0;
        while(i+len < length) //先判断可成倍的 前面的 序列
        {
            Merge(q,fu,i, i+m-1, i+len-1);
            i +=len;
        }

        // 
        if(i+m <length) //再判断不可成倍的 后面的 序列
        {
            Merge(q,fu,i,i+m-1,length-1);

        }
        tmp = q; q = fu; fu = tmp; //交换q,fu,以保证下一趟归并时,仍从q 归并到fu

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值