归并排序
简单理解思路
- 运用分治的方法,先把数组不断拆分,之后再边排序边合并
时间复杂度
- O(nlongn)
#include<stdio.h>
int i,j,a[10000],n;
void merge(int left,int middle,int right)
{
int b[10000],k;
i=left;//分治之后从小到大依次比较排序后返回到原数组中
j=middle+1;//定义右边的起始点
k=left;
while(i<=middle&&j<=right)//循环直到左右两边有一边的数组输入完全
{
if(a[i]<a[j])//如果左边小于右边,就在新数组中存入左边的值
b[k++]=a[i++];
else
b[k++]=a[j++];
}
while(i<=middle)
b[k++]=a[i++];
while(j<=right)
b[k++]=a[j++];
for(i=left;i<=right;i++)
a[i]=b[i];
}
void mergesort(int left,int right)
{
if(left==right)
return;
int middle=(left+right)/2;
mergesort(left,middle);//不断拆分,直至最小
mergesort(middle+1,right);//不断拆分,直至最小
merge(left,middle,right);//开始合并排序
}
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
mergesort(1,n);
for(i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
个人易错点,这里是while不是if,if只能执行一次,一次之后就退出了,要记得是while!! 永远错在这里
while(i<=middle)
b[k++]=a[i++];
while(j<=right)
b[k++]=a[j++];
我还是想解释一下,尽管今早检测中我差点又忘记了我上周详细写过的快速幂的模板
好的,举个栗子
比如现在需要对5 4 8 9 1 2 6排序
然后首先将他们不断二分,然后分到最后变成单独的数字了
5 4 8 9 1 2 6
现在将他们进行归并,在归并中排序,这个意思就是像下面这样,
5和4哪个小呢?4小,对的 ,所以把4先放在新数组里,然后再放入5,
5 4 8 9 1 2 原数组a
4 5新数组b
然后在把这两个值放回原数组中使原数组a变为
4 5 8 9 1 2
再排序第二组8和9,先放入8,然后放入9
4 5 8 9 1 2 原数组a
8 9新数组b
然后在把这两个值放回原数组中使原数组a变为
4 5 8 9 1 2
然后对4589进行放置,
4 5 8 9 1 2 原数组a
4 5 8 9新数组b
然后在把这两个值放回原数组中使原数组a变为
4 5 8 9 1 2
再排序1和2,先放入1,然后放入2
4 5 8 9 1 2 原数组a
1 2新数组b
然后在把这两个值放回原数组中使原数组a变为
4 5 8 9 1 2
最后将它们最后一次归并
4 5 8 9 1 2
比较两边的数字,4和1,1小,所以在新数组里先放入1,然后判断4和2,2小,存入2
然后右边没有值了,将左边剩下部分依次输入,最后将新数组b中的值再返回赋给a
得到最终结果啦,数组a为
1 2 4 5 8 9