A二路归并 递归法
归并排序愿原理:
该算法采用分治法(Divide and Conquer)先分后合
二路归并原理:
2个有序的序列,每次将他们最小的值做比较,把较小的拿出来放在第三个序列中。重复这个过程。如下图
void Merge(int* a,int lo,int hi){
int mid=(lo+ hi)>>1;
int i=lo,j=mid+1,k=0;
int *d=new int [hi-lo+1]();// 辅助数组
// 将左右区间的值进行比较,把较小的优先复制到辅助数组里
while(i<=mid && j<= hi)
{
if(a[i]<a[j])
{
d[k++]=a[i++];
}
else
{
d[k++]=a[j++];
}
}
// 将左区间或右区间还有剩余的值复制到辅助数组
while(i<=mid) d[k++]=a[i++];
while(j<= hi) d[k++]=a[j++];
//将数据从辅助数组复制到原数组相应位置
for(i=lo, k=0; i<=hi; i++,k++)
a[i]=d[k];
delete []d;
}
void MergeSort(int *a,int left,int right){
if(left<right){ //检查基本情况
int mid=(left+right)/2;
MergeSort(a,left,mid); //左半区间排序
MergeSort(a,mid+1,right); //右半区间排序
Merge(a,left,right); //合并
}
}
B二路归并 迭代法
也称作 直接归并排序
把相邻的数据段从c到d归并
template<class T>
void Merge(T c[],T d[],int start1,int end1,int end2)
{
int first=start1, //第一个数据段的索引
second=end1+1, //第二个数据段的索引
result=start1; //归并数据段的索引
//直到有一个数据段归并到归并段d
while ((first<=end1) && (second<=end2)) {
if(c[first]<=c[second])
d[result++] = c[first++];
else
d[result++] = c[second++];
}
//归并剩余元素
if(first > end1)
for(int q=second; q<= end2; q++){
d[result++]=c[q];
}
else
for(int q=first; q<=end1; q++){
d[result++]=c[q];
}
}
把相邻的两个数据段从x到y归并
template<class T>
void MergePass(T x[], T y[], int n, int segmentSize)
{//从x到y归并相邻的数据段
int i=0; //下一个数据段的起点
while(i<= n-2* segmentSize){//从x到y归并相邻的数据段
Merge(x,y, i, i+ segmentSize-1, i+2* segmentSize- 1);
i=i+ 2*segmentSize;
}
if(i+segmentSize< n)
Merge(x,y, i, i+segmentSize- 1, n-1); //剩余两个数据段
else
for(int j=i;j<n;j++) //只剩一个数据段,复制到y
y[j]=x[j];
}
用归并排序算法对数组元素进行排序
template<class> T
void MergeSort(T a[], int n)
{//使用归并排序对a[0,n-1]排序
Tt* b=new T [n]();
int segmentSize=1;
while(segmentSize<n){
MergePass(a, b, n, segmentSize); //从a到b的归并
segmentSize+= segmentSize;
MergePass(b, a, n, segmentSize);//从b到a的归并
segmentSize+= segmentSize;
}
delete [] b;
}