归并排序(递归与非递归)的实现

摘要:
(1)归并排序几乎以O(NlogN)的时间界实现,是典型的分治算法;
(2)归并排序的基本思路很简单:就是将目标序列分为两个部分,将两个子序列排序好之后,再将它们合并。注意到合并两个已排序的序列只需要O(N)的时间界。
(3)对两个子序列的排序显然也是通过递归的归并排序实现的。
(4)需要注意的一个小细节是,当子序列的元素很少时,继续调用归并排序未必是一件划算的事.因此可以设置一个边界,当元素个数少于这个值时就掉用最简单的插入排序.
【1】合并的过程
合并的过程相对简单,用两个指针指向两个子序列的开始点,然后比较它们的大小.将较小的一个放入新的数组.然后将指向较小元素的指针前移一位。继续这个过程直到某一个指针达到边界.然后将另一个子序列的剩余所有元素都置入新的数组.
【2】注意的细节:如果每一次递归都创建一个新的数组那么将会占用很多的空间.因此合理的做法是在进入递归之前创建两个数组,然后用两个变量Left,Right标志子序列的边界。每一次合并的过程都是把A[Left1]到A[Right1],A[Left1+1]到A[Right2]合并到B[left1]到B[Right2];

#include "stdafx.h"
#include "malloc.h"
#include "stdlib.h"
#include "string.h"
#define Max 10000000
int Min(int a ,int b)
{
    return a < b ? a:b;
}
void Merge(int *A,int *tmp,int Left1,int Right1,int Left2, int Right2)
{
    if(Left1==Right1&&Right1==Left2&&Left2==Right2)//只有一个元素不用合并
    return;

    int point1 = Left1,point2 = Left2,k = Left1;
    //int tmp[9];
    while(point1 <= Right1 && point2 <= Right2)
    {
    if(A[point1] <= A[point2])
        tmp[Left1++] = A[point1++];
    else
        tmp[Left1++] = A[point2++];
    }
        while(point1 <= Right1)
            tmp[Left1 ++] = A[point1++];
        while(point2 <= Right2)
            tmp[Left1++] = A[point2++];
    for (Left1 = k;Left1<= Right2;Left1++)
    {
        A[Left1] = tmp[Left1];
    }
}

【2】真正的排序

void Mergesort(int *A,int *tmp,int Left,int Right)
{
    int Center;
    if(Left == Right)//只有一个元素
        return;
    Center = (Left + Right)/2;
    Mergesort(A,tmp,Left,Center);
    Mergesort(A,tmp,Center + 1,Right);
    //下面合并
    Merge(A,tmp,Left,Center,Center+1,Right);
}

【3】以上的程序都是用递归的办法实现。下面用非递归的办法实现归并排序.
非递归的基本思路
(1)我们应该每次对2^i长度的子序列进行合并。例如最开始对长度为1的相邻子序列进行合并;然后对长度为2的相邻的子序列进行合并。代码如下

void Mergesort2(int *A,int *tmp,int N)
{
    //非递归归并
    int test[9];

    int number = 1;//每次合并个数
    int i,Center,end;
    while(number <= N-1)
    {
    for( i = 0;   i + number<= N ; i += number)
    {
        end = i + number - 1;
        Center = (i + end)/2;
        Merge(A,tmp,i,Center,Center+1,end);

    }
    if (i <= N-1)
    {
        //合并多出的元素
            Merge(A,tmp,i-number,i-1,i,N-1);
    }
    number *= 2;
    }
}
void Msort(int A[],int N)
{
    int i = 1,cutoff,j;
    while(i <= N)
    {
        i *= 2;
    }
    cutoff = i - N;
    int *B = (int *)malloc(sizeof(int)*i);
    int *tmp = (int *)malloc(sizeof(A)*N);
    Mergesort2(A,tmp,N);
    free(tmp);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值