【归并排序】

来源:互联网 发布:图标上下不停跳动js 编辑:程序博客网 时间:2024/06/18 08:46

   归并排序(Merging Sort)

 归并排序就是将两个或两个以上的有序表合并成一个有序表的过程。将两个有序表合并成一个有序表的过程称为2-路归并。

归并排序算法的思想是:

假设初始序列含有n个记录,则可看成n个有序的子序列,每个字序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,...,如此重复,直到一个长度为n的有序序列为止。

例 已知待排序记录的关键字序列为{49,38,65,97,76,13,27},给出2-路归并排序法进行排序的过程

2-路归并排序中的核心操作是,将待排序序列中前后相邻的两个有序序列归并为一个有序序列。

相邻两个有序子序列的归并

  [算法思想]

   设两个有序表存放在同一数组中相邻的位置上:R[low..mid]和R[mid+1..high],每次分被从两个表中取出一个记录进行关键字的比较,将较小者放入T[low..high]中,重复此过程,直至其中一个表为空,最后将另一非空表中余下的部分直接复制到T中。
  [算法描述]
  
void Merge(int R[],int T[],int low,int mid,int high)  {/*将有序表R[low..mid]和R[mid+1..high]归并为有序表T[low..high]*/int i=low;int j=mid+1;int k=low;while(i<=mid&&j<=high)    /*将R中记录由小到大的并入T中*/{if(R[i]<=R[j])T[k++]=R[i++];else T[k++]=R[j++];}while(i<=mid) T[k++]=R[i++];/*将剩余的R[i..mid]复制到T中*/while(j<=high) T[k++]=R[j++];/*将剩余的R[j..high]复制到T中*/  }

     假设每个子序列的长度为h,则一趟归并排序需要调用[n/2h]次算法merge进行两两归并,得到前后相邻、长度为2h的有序段,整个归并排序序进行[log2n]趟。与快速排序类似,2-路归并排序也可以利用划分为子序列的方法递归实。首先把整个待排序序列划分为两个长度大致相等的子序列,对这两个子序列分别递归地进行排序,然后再把他们归并。典型的分治思想,分解,解决,合并。

归并排序

[算法思想]

2-路归并排序将R[low..high]中的记录归并排序后放入T[low..high]中。当序列长度等于1时,递归结束,否则:

1)将当前序列一分为二,求出分裂点mid=(low+high)/2;                  

2)对子序列R[low..mid]递归,进行归并排序,结果放入S[low..mid]中。

3)对子序列R[mid+1..high]递归,进行归并排序,结果放入S[mid+1..high]中。

4)调用算法Merge,将有序的两个子序列S[low..mid]和S[mid+1..high]归并为一个有序的序列T[low..high];

 [算法描述] 
void MSort(int R[],int T[],int low,int high){/*R[low..high]归并排序后放入T[low..high]中*/int mid=0;int S[101];  /*辅助数组*/if(low==high)T[low]=R[low];else{mid=(low+high)/2;           /*将当前序列一分为二,求出分裂点mid*/MSort(R,S,low,mid);         /*对子序列R[low..mid]递归归并排序,结果放入S[low..mid]*/MSort(R,S,mid+1,high);      /*对子序列R[mid+1..high]递归归并排序,结果放入S[mid+1..high]*/Merge(S,T,low,mid,high);    /*将S[low..mid]和S[mid+1..high]归并到T[low..high]*/}}  void MergeSort(int L[],int n) {    MSort(L,L,1,n); }
 [算法分析]
1)时间复杂度
    当有n个记录时,需进行[log2n]趟归并排序,每一趟归并,其关键字比较次数不超过n,元素移动次数都是n,因此,归并排序的时间复杂度为O(nlog2n)。
2)空间复杂度
    用顺序表实现归并排序时,需要和待排序记录个数相等的辅助存储空间,所以空间复杂度为O(n);

 [完整代码]

#include<iostream>using namespace std;void Merge(int R[],int T[],int low,int mid,int high)  {/*将有序表R[low..mid]和R[mid+1..high]归并为有序表T[low..high]*/int i=low;int j=mid+1;int k=low;while(i<=mid&&j<=high)    /*将R中记录由小到大的并入T中*/{if(R[i]<=R[j])T[k++]=R[i++];else T[k++]=R[j++];}while(i<=mid) T[k++]=R[i++];/*将剩余的R[i..mid]复制到T中*/while(j<=high) T[k++]=R[j++];/*将剩余的R[j..high]复制到T中*/  }void MSort(int R[],int T[],int low,int high){/*R[low..high]归并排序后放入T[low..high]中*/int mid=0;int S[101];  /*辅助数组*/if(low==high)T[low]=R[low];else{mid=(low+high)/2;           /*将当前序列一分为二,求出分裂点mid*/MSort(R,S,low,mid);         /*对子序列R[low..mid]递归归并排序,结果放入S[low..mid]*/MSort(R,S,mid+1,high);      /*对子序列R[mid+1..high]递归归并排序,结果放入S[mid+1..high]*/Merge(S,T,low,mid,high);    /*将S[low..mid]和S[mid+1..high]归并到T[low..high]*/}}  void MergeSort(int L[],int n) {    MSort(L,L,1,n); /*注意排序的起始位置是1*/ }  int main()  {  int ans[5]={0,7,2,36,1};  MergeSort(ans,4);  for(int i=1;i<=4;i++)  cout<<ans[i]<<" ";  return 0;  }
 [运行结果]



1 0
原创粉丝点击