归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。值得注意的是归并排序是一种稳定的排序方法。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
如 设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11;
归并排序的最好、最坏和平均时间复杂度都是O(nlogn),而空间复杂度是O(n),比较次数介于(nlogn)/2和(nlogn)-n+1,赋值操作的次数是(2nlogn)。因此可以看出,归并排序算法比较占用内存,但却是效率高且稳定的排序算法。
code
/*
归并排序
*/
#include <stdio.h>
#include <stdlib.h>
#define A 7
int s[A]={2,39,4,5,82,7,64};
void merge(int s[],int b,int m,int e) //两序列进行合并
{
int i,j,k;
int temp[A];
i=b;
k=b;
j=m+1;
while(i<m+1 && j<e+1) //小数排在寄存数组的前面
{
if(s[i]<s[j])
{
temp[k++]=s[i++];
}
else
{
temp[k++]=s[j++];
}
}
if(i<m+1) //处理未处理完的部分
{
while(i<m+1)
{
temp[k++]=s[i++];
}
}
if(j<e+1)
{
while(j<e+1)
{
temp[k++]=s[j++];
}
}
for(i=b;i<=e;i++) //更新原数组
{
s[i]=temp[i];
}
return;
}
void mergesort(int s[],int b,int e) //归并排序的递归程序
{
int m;
if(e>b)
{
m=(b+e)/2; //不断划分小区间进行归并操作
mergesort(s,b,m);
mergesort(s,m+1,e);
merge(s,b,m,e);
}
return;
}
int main(void)
{
int i;
int temp[A];
mergesort(s,0,A-1);
printf("The merge sort result is:\n");
for(i=0;i<A;i++)
{
printf("%d ",s[i]);
}
printf("\n");
system("pause");
return 0;
}