7--归并排序

 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

归并排序思想:

多次将两个或者两个以上的有序表合并成一个新的有序表。

最简单的归并:是直接将两个有序的子表合并成一个有序的表。

最简单的归并,又被称为2-路归并

排序前:

172306_8gxa_2290420.png

排序后:

172306_AMYY_2290420.png

void Merge(int R[] ,int low,int mid,int high)
{
    
    int * R1;
    
    int i = low,j = mid+1 , k= =0;
    
    //动态分配空间R1,用于保存合并结果
    R1 = (int *)malloc((high - low +1)*sizeof(int));
    
    //两段均未扫描完成时合并
    while(i <= mid && j <=high)
    {
        if(R[i] < R[j])
        {
            R1[k] = R[i];
            i++;
            k++;
        }
        else
        {
            R1[k] = R[j];
            j++;
            k++;
        }
    }
    
    //将第一段剩余的部分复制到R1
    while( i <= mid)
    {
        R1[k] = R[i];
        i++;
        k++;
    }
    
    //将第二段余下的部分复制到R1
    while(j <= high)
    {
        R1[k] = R[j];
        j++;
        k++;
    }
    
    //将合并后的结果复制回R
    for(i = 0 ;i < high;i++)
        R[low+i] = R1[i];
}

归并排序的过程:

如何获取到两个已经有序的数列呢? 

开始的时候,把单个元素作为一个序列,然后把相邻的两个元素合并为一个有序的队列。

即:第一趟,把相邻的两个元素合并为一个有序的序列。合并后序列长度为2.

第二趟:把第一趟合并完的有序序列看成一个整体,和相邻的有序序列合并。合并后序列的长度为4

第三趟:同上,合并后序列的长度为8.

174305_2SDl_2290420.png

根据上面的描述,代码如下:

void MergeSort(int R[],int n)
{
    int length;
    
    //合并的长度从1开始,每次都乘以2
    for(length = 1; length <n;length = 2*length)
    {
        //进行一趟合并
        MergePass(R,length,n);
    }
    
    //如果前面合并完后,还有剩余的序列,比如上面的1 5序列,则把剩余的序列和前面合并好的序列继续合并
    if(i+length -1 <n)
    Merge(R,i+length-1,n-1);
}

void MergePass(int R[],int length,int n)
{
    int i;
    
    //i+2*length-1 <n 是为了保证 最后合并的两个序列的下标,不会大于序列的实际的下标。
    for(i = 0; i+2*length-1 <n; i+=2*length)
    {
        Merge(R,i,i+length-1;i+2*length-1);
    }
    
    
}


感觉上面的代码好复杂啊。

网上看到了一个比较简单的代码:

void mergeSort(int R[], int first, int last)
{
    if(first < last)
    {
        int mid = (first+last)/2;
        mergeSort(R,first,mid); //左边有序
        mergeSort(R,mid+1,last); //右边有序
        Merge(R,first,mid,last);//再将两个有序的序列合并
    }
}

虽然代码简单了,但是原理还是上面说到的原理。当分出来的小组只有一个数据时,可以认为小组内已经达到有序,然后再合并相邻的两个小组,就可以了。

这样通过先递的分解数列,再合数列就完成了归并排序。




转载于:https://my.oschina.net/aslanjia/blog/646865

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值