合并排序(归并排序)

【合并排序】

又称为归并排序,合并排序是台湾所称?

分治模式: 分解 解决 合并

分解:将n个元素分成两个n/2个元素的子序列

解决:用合并排序法对两个子序列递归地排序

合并:合并两个已排序的子序列以得到排序结果

(对子序列排序时,其长度为1时递归结束。每个元素被视为以排序的)

【合并排序,源自算法导论】

MERGE(A,p,q,r)
    n1 = q-p+1
    n2 = r-q
    create arrays L[1..n1+1] and R[1..n2+1]
    for i = 1 to n1
        L[i] = A[p+i-1]
    for j = 1 to n2
        R[j] = A[q+j]
    L[n1+1] = ∞
    R[n2+1] = ∞
	i = 1
	j = 1
	for k = p to r
        if L[i] <= R[j]
			A[k] = L[i]
			i=i+1   
		else 
			A[k] = R[j]
            j=j+1 


MERGE-SORT(A,p,r)
	if p < r
		q = [(p+r)/2]
        MERGE-SORT(A,p,q)
        MERGE-SORT(A,q+1,r)
        MERGE(A,p,q,r) 



【C++ 代码一】

修改于2013/4/5

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <math.h>
#include <time.h>
#include <cstdlib>
#include <stack>

using namespace std;

const int IMAX = 100000;
const int N = 1000;

int *L = new int[N];
int *R = new int[N];

void Merge(int *A,int p,int q,int r)
{
    int i,j;
    int len_l = q-p+1;
    int len_r = r-q;

    for(i = 0;i<len_l;i++)
        L[i]=A[p+i];
    L[len_l] = IMAX;

    for(j = 0;j<len_r;j++)
        R[j]=A[q+j+1];
    R[len_r] = IMAX;

    i = j = 0;
    for(int k=p;k<=r;k++)
    {
        if(L[i] <= R[j])
            A[k] = L[i++];
        else
            A[k] = R[j++];
    }

}

void Merge_Sort(int *A,int p,int r)
{
    if(p < r)
    {
        int q = (p+r)/2;
        Merge_Sort(A,p,q);
        Merge_Sort(A,q+1,r);
        Merge(A,p,q,r);
    }
}

int main()
{
    const int num = 10;
    int Arr[num];
    srand((unsigned)time(NULL));
    for(int i=0;i<num;i++)
        Arr[i] = rand()%100;

    cout<<"before quick sort:"<<endl;
    for(int i=0;i<num;i++)
        cout<<Arr[i]<<" ";
    cout<<endl;

    Merge_Sort(Arr,0,num-1);

    cout<<"after quick sort:"<<endl;
    for(int i=0;i<num;i++)
        cout<<Arr[i]<<" ";
    cout<<endl;

    delete [] L;
    delete [] R;
    return 0;
}
/*
实验结果:
before quick sort:
69 80 86 49 35 66 12 96 71 29
after quick sort:
12 29 35 49 66 69 71 80 86 96
*/


 

【C++ 代码二 带详细注释】

写于2011/12/25

#include <iostream>
#include <climits>
#include <stdlib.h>

using namespace std;

/*将两段序列按顺序合成一段*/
void Merge(int *a,int p,int q,int r)
{
    int i,j;
    int len_l=q-p+1;      //左序列长度
    int len_r=r-q;        //右序列长度
    int *left=(int *)malloc(sizeof(int)*(len_l+2)); //为左序列申请空间
    int *right=(int *)malloc(sizeof(int)*(len_r+2));//为右序列申请空间
    for(i=1; i<=len_l; i++) //将a[p...q]放在左序列中
    {
        left[i]=a[p+i-1];
    }
    left[len_l+1]=INT_MAX;//在左序列最后一个位置放置一个哨兵
    for(j=1; j<=len_r; j++) //将a[q+1...r]放在右序列中
    {
        right[j]=a[q+j];
    }
    right[len_r+1]=INT_MAX;//在右序列最后一个位置放置一个哨兵
    //下面的思想是已经有两端序列:left,right,并且这两段都是
    //排好序的。现在比较这两段的第一张,然后抽掉(也就是i++或j++)
    //张较小的放入到A[k]中,k++,继续比较这两段的第一张,直至没有元素为止。
    //哨兵的作用是告诉程序,这一段已经结束了,直接取另一段的放入A[k++]中即可。
    //哨兵是这么工作的:如果有一段先结束,那么这一段的第一张就是哨兵了
    //另一段肯定比哨兵小,所以放入A数组的一直就是这另一段,直至另一段也有了哨兵。
    i=j=1;
    for(int k=p; k<=r; k++)
    {
        if(left[i] <= right[j])
        {
            a[k]=left[i];
            i++;
        }
        else
        {
            a[k]=right[j];
            j++;
        }
    }
}
/*将一段序列分为两段,a[p...q],a[q+1..r],然后在再合并*/
void MergeSort(int *a,int p,int r)
{
    //此处默认单独一个数是已经排完序的。
    //程序不断递归调用,直到p==r也就是一个数的时候。
    //然后再一步步合并,(1,1)合并成2,(2,2)合并成4。。
    if(p<r)
    {
        int q=(p+r)/2;
        MergeSort(a,p,q);
        MergeSort(a,q+1,r);
        Merge(a,p,q,r);
    }
}

int main()
{
    int array[8]= {1,3,5,2,4,7,0,1};
    int len=sizeof(array)/sizeof(int);
    MergeSort(array,0,len-1);
    for(int i=0; i<len; i++)
        cout<<array[i]<<" ";
    return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值