#include <iostream>
#include <cstdio>
using namespace std;
//归并排序
/*
原理:分而治之,然后合之。
一分为二,然后从两个数组中头部依次拿出较小的值放入辅助数组中,从而达到排序的目的。
*/
int a[9]={0,1,54,77,24,97,32,8,21};
int t[9];
void fun(int l,int r)
{
if(l==r) return; //一开始给出递归停止的条件
int mid=(l+r)/2; //由于int的截断,无论奇偶都是适用的
/* 理解递归函数,要从功能单元的角度出发。
在这里fun函数功能单元就是:一分为二,然后从两个数组的头部按大小顺序拿元素放入辅助数组中。
所以理解的时候可以先去掉这两行递归的代码,理解fun实现的功能。
然后再利用递归的思想:
要处理大的问题,就把它分解成为问题解决模式相同的子问题,在这里表现为:要让整个数组
排好序,就得先一分为二,按序取出。可是要保证第一次按序取出后数组就有序,就得保证
第一次分成的两个数组本来就排好了序。(这一点自行验证),为了保证这一点,就需要在“合”之前递归。(因为这是fun的功能)
这样一来就确定了递归代码的位置。
*/
fun(l,mid);
fun(mid+1,r);
int p=l,q=mid+1,f=l; //f用来记录一开始l的值(后面l会变)
while(p<=mid && q<=r) //从两个分好的数组头部开始拿元素
{
if(a[p]<=a[q])
t[l++]=a[p++];
if(a[q]<a[p])
t[l++]=a[q++];
}
while(p<=mid) //如果左边数组没拿完
t[l++]=a[p++];
while(q<=r)
t[l++]=a[q++]; //如果右边数组没拿完
for( ;f<=r;f++) //从辅助数组赋值回去
a[f]=t[f];
}
int main()
{
fun(1,8);
for(int i=1;i<=8;i++)
cout<<a[i]<<" ";
return 0;
}
备注:
1.以上代码中,fun函数里的最后一步:t数组覆盖a数组是必不可少的,不能省略这一步并且认为函数运行完后的t数组就是排好序的数组,这是错误的观点。另外,t++,p++,q++在上下两次的衔接(同时从两个数组中拿和他下面的从一个没拿完的数组)过程中并没有漏掉上一次的最后一个p/q。
2.红色部分代码,是添加递归思想后fun函数所增加的代码