合并排序(归并排序)

来源:互联网 发布:什么是数据转换 编辑:程序博客网 时间:2024/06/05 10:03

【合并排序】

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

分治模式: 分解 解决 合并

分解:将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 = 1j = 1for 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 < rq = [(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 29after 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;}