合并排序算法
待排序元素分为不同的子集合进行排序,最终将排好序的子集合合并成有序集合
思路分析
1.递归思想是将区间不断分割成小区间进行排序(n,n/2,n/4,n/16…)
2.非递归思想是将小区间内进行排序,并不断将小区间的长度扩大(1,2,4,8…)
详细算法思路见代码注释
代码实现
/*递归式合并排序框架*/
template <class Type>
void mergesort(Type a[],int left,int right) /*传入数组和区间范围*/
{
if(left<right) /*设置递归结束条件*/
{
int i=(left+right)/2; /*将区间一分为二*/
mergesort(a,left,i); /*左半区间递归*/
mergesort(a,i+1,right); /*右半区间递归*/
merge(a,b,left,i,right); /*将当前区间左右两半段合并排序,给到数组b*/
copy(a,b,left,right); /*将数组b复制回数组a*/
}
}
/*非递归式合并排序框架*/
template <class Type>
void mergesort(Type a[],int n) /*传入数组和数组大小*/
{
Type *b=new Type[n]; /*新开一个数组b,大小为n*/
int s=1; /*s代表进行排序小区间的大小*/
while(s<n) /*结束条件为整个大区间都已排好序*/
{
mergepass(a,b,s,n); /*将a的小区间排序,结果给到数组b*/
s=2s; /*将小区间范围扩大一倍*/
mergepass(b,a,s,n); /*将b的小区间排序,结果给回数组a*/
s=2s; /*将小区间范围扩大一倍,进入下次循环*/
}
}
/*每两个相邻小区间结合过程*/
template <class Type>
void mergepass(Type a[],Type b[],int s,int n)
{
int i=0; /*i代表当前组合(长度大小为2s)的首地址*/
while(i<=n-2*s) /*遍历当前所有组合*/
{
merge(x,y,i,i+s-1,i+2*s-1); /*相邻区间排序*/
i=i+2*s; /*移动到下一个组合中去*/
}
if(i+s<n) /*如果剩下的够s,不够2s了*/
merge(x,y,i,i+s-1,n-1); /*需进行比较*/
else /*如果剩下的不够s了*/
{
for(int j=i;j<=n-1;j++) /*不需要进行比较了*/
y[j]=x[j];
}
}
/*相邻小区间排序过程*/
template <class Type>
void merge(Type a[],Type b[],int left,int middle,int right)
{
int i=left,j=middle+1,k=left;
/*i,j分别去遍历原数组前后两个半区间的变量,k去遍历新数组的变量*/
while(i<=middle&&j<=right) /*有一个遍历完毕,则终止循环*/
{
if(a[i]<=a[j]) /*前小,则将前其放到新数组内*/
b[k++]=a[i++];
else
b[k++]=a[j++]; /*后小,则将后其放到新数组内*/
if(i>middle) /*前面遍历完了,后面的直接接在新数组后面*/
{
for(int p=j;p<=right;p++)
b[k++]=a[p];
}
else /*后面遍历完了,前面的直接接在新数组后面*/
{
for(int q=i;q<=middle;q++)
b[k++]=a[q];
}
}
}