二路归并排基本思想:把拥有n个数据的数组看做n个有序序列,然后两两归并,得到n/2组有序序列;重复上述操作,达到n/4组有序序列;重复上述操作,直到n个数据均为有序。
平均情况的时间复杂度 最好情况的时间复杂度 最坏情况的时间复杂度 空间复杂度
O(nlog2(n)) O(nlog2(n)) O(nlog2(n)) O(n)
数据存储在a[1]~a[n],两个相邻有序序列归并一次的代码实现
void Merge(Type a[],Type b[],int s,int m,int t) { int i=s,j=m+1,k=s; while(i<=m&&j<=t) { if(a[i]<=a[j]) { b[k++]=a[i++]; } else { b[k++]=a[j++]; } } if(i<=m) { while(i<=m) { b[k++]=a[i++]; } } else { while(j<=t) { b[k++]=a[j++]; } } }
数据进行一趟归并的代码实现:
当第一个序列的下标为i时
(1)若i<=n-2h+1,待归并数据还有两个相邻的长度为h的序列;
(2)若i<n-h+1,待归并数据有一个长度为h的序列,还有一个不满h的序列
(3)若i>=n-h+1,只剩下一个有序序列,直接将有序序列传送给。
template<class Type> void MergePass(Type a[],Type b[],int n,int h) { int i=1; while(i<=n-2*h+1) { Merge(a,b,i,i+h-1,i+2*h-1); i+=2*h; } if(i<n-h+1) { Merge(a,b,i,i+h-1,n); } else { for(int k=i;k<=n;k++) { b[k]=a[k]; } } }
二路归并的代码实现:
#include<iostream> using namespace std; template<class Type> //数据存储在人r[1]~r[n] void Merge(Type a[],Type b[],int s,int m,int t) { int i=s,j=m+1,k=s; while(i<=m&&j<=t) { if(a[i]<=a[j]) { b[k++]=a[i++]; } else { b[k++]=a[j++]; } } if(i<=m) { while(i<=m) { b[k++]=a[i++]; } } else { while(j<=t) { b[k++]=a[j++]; } } } template<class Type> void MergePass(Type a[],Type b[],int n,int h) { int i=1; while(i<=n-2*h+1) { Merge(a,b,i,i+h-1,i+2*h-1); i+=2*h; } if(i<n-h+1) { Merge(a,b,i,i+h-1,n); } else { for(int k=i;k<=n;k++) { b[k]=a[k]; } } } template<class Type> void MergeSort1(Type a[],int n) { int h=1; Type b[n+1]; while(h<n) { MergePass(a,b,n,h); h=2*h; MergePass(b,a,n,h); h=2*h; } } int main() { int a[8]={0,49,27,65,97,76,13,38}; for(int i=0;i<7;i++) cout<<a[i]<<" "; cout<<endl; MergeSort1(a,7); for(int i=0;i<7;i++) cout<<a[i]<<" "; cout<<endl; return 0; }