归并排序
归并排序是典型的分治法(把一个复杂的问题分成两个或者多个相同或者类似的子问题)的应用。该算法将已经有序的子序列合并,得到完全有序的序列;也就是先将每个子序列排好序,再使子序列段间有序。
算法也分为两步,一个是‘分’,也就是将原数组分为两个子数组的过程。还有一个就是‘治’,将两个有序数组合成一个大的数组。
在进行‘分’这一步时,要不断划分到每个子序列只剩下一个元素,这时序列可以看作是有序表。
进行‘治’时,将子序列两两合并,每合并一次,就会产生一个新的更长的有序表,重复这一步,直到最后只剩下一个子表,这就是已经排好序的线性表。
图解(摘自努力的老周):
初始数组:{8,4,5,7,1,3,6,2}
治的阶段,上图的最后一步
代码如下:
#include"stdio.h"
void merge(int a[],int l,int r,int mid)
{
int b[r-l+1],i,j,k;
for(k=l;k<=r;k++)
b[k-l]=a[k];
i=l;
j=mid+1;
for(k=l;k<=r;k++)
{
if(i>mid)
{
a[k]=b[j-l];
j++;
}
else if(j>r)
{
a[k]=b[i-l];
i++;
}
else if(b[i-l]>b[j-l])
{
a[k]=b[j-l];
j++;
}
else
{
a[k]=b[i-l];
i++;
}
}
}
void merge_sort(int a[],int l,int r)
{
int mid;
if(l>=r)
return ;
mid=(l+r)/2;
merge_sort(a,l,mid);
merge_sort(a,mid+1,r);
merge(a,l,r,mid);
}
void mergesort(int a[],int l,int r)
{
merge_sort(a,l,r-1);
}
main()
{
int a[105],n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
mergesort(a,0,n);
for(i=0;i<n;i++)
printf("%d ",a[i]);
}