归并排序--详解
算法描述:是分治法的典型应用。多次将两个有序序列全并成一个有序序列。最终使序列有序。
算法思路:只有一个元素时总是有序的,所以将排列数组a[n]看作是n个长度为1的有序元素,对相邻的两个子元素两两合并成有序子数组,再对有序子数组进行两两合并,直到只有一个长度为n的有序数组,完成排序。
性能分析:稳定
归并排序时的时间复杂度为O(nlgn) 其主要思想是分治法(divide and conquer),分就是要将n个元素的序列划分为两个序列,再将两个序列划分为4个序列,
直到每个序列只有一个元素,最后,再将两个有序序列归并成一个有序的序列。
例如两个序列:
要归并成一个有序的序列,按照我们常规的方法,我们每次从两个列表开头元素选取较小的一个,直到某一个列表到达底部,再将另一个剩下部分顺序取出。其实如果将每个元素最后添加一个最大值,则无需判断是否达到列表尽头。
下面是用递归方法实现的C语言代码:
int s[MAXN],temp[MAXN];//s为存放排序元素的数组,temp为存放临时排序的数组
void merge(int a[],int l,int mid,int r)//l为下界,mid为中间值,r为上界
{
int i,j,k;
i = k =l;
j = mid+1;
while(i<=mid && j<=r)
{
if(a[i]<a[j])
{
temp[k++] = a[i];
i++;
}
else
{
temp[k++]=a[j];
j++;
}
}
while(i<=mid)
{
temp[k++]=a[i];
i++;
}
while(j<=r)
{
temp[k++]=a[j];
j++;
}
for(i=l;i<=r;i++)
{
a[i] = temp[i];
//printf("%d ",temp[i]);
}
//printf("\n");
}
void mergesort(int a[],int l,int r)
{
int mid=0;
if(l<r)
{
mid = (l+r)>>1;
mergesort(a,l,mid);
//printf("A1A %d %d \n",l,mid);
mergesort(a,mid+1,r);
//printf("A2A %d %d \n",mid+1,r);
merge(a,l,mid,r);
//printf("A3A %d %d %d\n",l,mid,r);
}
}