1、前面说到直接插入排序的效率要比选择和冒泡高,特别是对于基本有序的序列,直接插入排序更有优势;而归并排序就是利用这种特点,先使子序列基本有序,然后逐渐合并序列(利用插入),最后使整个序列有序。归并在数据结构中的定义就是将两个或两个以上的有序表组合成一个新表的过程;归并排序就是利用归并的思想实现的排序的方法,它的原理是:假设有n个记录,则可以看成n个有序子序列(每个子序列长度为1),然后两两归并得到「n/2」个长度为1或2的有序子序列,然后再两两归并......如此重复直至得到一个长度为n的有序序列为止;这种非方法称为2路归并排序,同时也是用的最多的归并排序。
2、归并排序的实现由递归和非递归两种,递归算法代码清晰、简洁高效,但是会占用内存;非递归算法采用迭代思想,较递归算法更省内存且性能进一步提高;因此,在使用归并排序时应尽量使用非递归(迭代)方法。
3、非递归归并排序代码如下
3.1 将有序的SR[i...m]和SR[m+1...n]归并为有序的TR[i...n]
void merge(int SR[],int TR[],int i,int m,int n)
{
int j,k,l;
for(j=m+1,k=i;i<=m && j<=n;k++){ //将SR中的记录由小到大并入TR
if(SR[i]<SR[j])
TR[k]=SR[i++];
else
TR[k]=SR[j++];
}
if(i<=m){
for(l=0;l<=m-i;l++)
TR[k+l]=SR[i+l]; //将剩余的SR[i...m]复制到TR
}
if(j<=n){
for(l=0;l<=n-j;l++)
TR[k+l]=SR[j+l]; //将剩余的SR[j...n]复制到TR
}
}
3.2 将SR中相邻长度为S的子序列两两归并到TR
void merge_pass(int SR[],int TR[],int s,int n)
{
int i=1;
int j;
while(i <= n-2*s+1){
merge(SR,TR,i,i+s-1,i+2*s-1);//两两归并
i=i+2*s;
}
if(i<n-s+1) //归并最后两个序列
merge(SR,TR,i,i+s-1,n);
else //若最后只剩下单个子序列
for(j=i;j <= n;j++)
TR[j]=SR[j];
}
3.3 归并排序迭代实现
对顺序表L作非递归归并排序
void merge_sort(SqList *L)
{
int* TR=(int*)malloc(L->length*sizeof(int)); //申请空间
int k=1;
while(k < L->length){
merge_pass(L->array,TR,k,L->length);
k=2*k; //子序列长度加倍
merge_pass(TR,L->array,k,L->length);
k=2*k; //子序列长度加倍
}
}