基本思想:
其实归并排序也是一种分治的思想,就是将大问题拆解成为小问题,将一个大的数组先拆分成若干个小的数组,然后再将它们一点点的合并起来,从而形成一个有序的数组。
基本步骤:
确定分界点,将数组一分为二 mid = (left + right ) / 2
递归排序,将数组再次一分为二,直到数组足够小为止
归并,合二为一。(要借助一个辅助数组tmp)
过程演示:
先分后合的思想。分很简单,基本上都看得懂。所以下面我就着“怎么合”展开分析一波
其实还是用到双指针的思想
分别用i,j指针指向两个子序列的首位,并进行比较。将较小的数写入辅助数组tmp中,随后指针移动。
模板代码展示:
void merge_sort(int *q,int l,int r)
{
if(l>=r) return ; // 如果当前区间只有一个元素,则完成‘分’的工作
int mid = l+r>>1; // 确定分界点->取中点
merge_sort(q,l,mid); //递归左边
merge_sort(q,mid+1,r); //递归右边
int tmp[1001]={0}; //定义辅助数组,一般定义为全局变量,这里是为了告诉你有这个东西
int k=0,i=l,j=mid+1; //确定左右区间的起点
//合的过程
while(i<=mid&&j<=r)
if(q[i]<=q[j])tmp[k++]=q[i++];
else tmp[k++]=q[j++];
//这两行只会执行其中一行
while(i<=mid)tmp[k++]=q[i++];
while(j<=r)tmp[k++]=q[j++];
//把辅助数组里的数据导回到原数组里
for(i=1,j=0,i<=r;i++,j++)q[i]=tmp[j];
}
时间复杂度的分析
归并排序的时间复杂度稳定为 O(Nlog N)
因为分的过程是O( logN)的复杂度,而合的过程是O(N)