归并排序(Merging Sort)的原理是假设初始序列含有n个记录,则可以看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或者1的子序列;再两两归并,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
以下程序在DEV C++中调试运行通过。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct
{
int r[10];//用于存储要排序的数组,r[0]用作烧饼或临时变量
int lenght;
}SqList;
//将有序的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];
}
if(j<=n)
{
for(l=0;l<=n-j;l++)
TR[k+l]=SR[j+l];
}
}
//将SR[]中相邻长度为s的子序列两两归并到TR[]
void MergePass(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];
}
//对顺序表L做归并非递归排序
void MergeSort2(SqList *L)
{
int* TR=(int*)malloc(L->lenght*sizeof(int));//申请额外空间
int k=1;
while(k<L->lenght)
{
MergePass(L->r,TR,k,L->lenght);
k=2*k;//子序列长度加倍
MergePass(TR,L->r,k,L->lenght);
k=2*k;
}
}
int main()
{
SqList L;
int k;
L.lenght=9;
int temp[10] ={0,9,1,5,8,3,7,4,6,2};
memcpy(L.r, temp, 10*sizeof(int));
printf("归并排序前:");
for(k=1;k<10;k++)
printf("%d,",L.r[k]);
printf("\n");
MergeSort2(&L);
printf("归并排序后:");
for(k=1;k<10;k++)
printf("%d,",L.r[k]);
printf("\n");
}
运行结果如图所示。
该算法的时间复杂度为O(nlogn),空间复杂度为O(n)。