归并排序思想
自上而下的递归
对一个数组(str)选中一个中间位置(mid=(start+end)/2),分别进行左递归(mergeSort(str,start,mid,length)),右递归(mergeSort(str,mid+1,end,length)),在回朔的时候分别对以中间为分割的数组进行排序(merge(str,start,end,mid)),此时是一个归并的过程,这是自上而下的方法。
自下而上的递归
自下而上归并其实就是自上而下的时候的回朔过程,先对每一个数字排序,在两两排序,在对结果两两排序,直到完成。
具体代码实现(自上而下)
int merge(long *str,int start,int end,int mid){
long *tmp = (long *)malloc(sizeof(long)*(end-start+1));
int i=start;
int j=mid+1;
int k=0;
while(i<=mid && j<=end){
if(str[i]<str[j])
tmp[k++]=str[i++];
else
tmp[k++]=str[j++];
}
while(i<=mid)
tmp[k++] = str[i++];
while(j<=end)
tmp[k++] = str[j++];
for(i=start;i<=end;i++)
str[i]=tmp[i-start];
free(tmp);
}
int mergeSort(long *str,int start ,int end,int length){
if(str == NULL || start <0 || end >length || length <=0 || end <= start)
return ;
int mid = (start + end )/2;
mergeSort(str,start,mid,length);
mergeSort(str,mid+1,end,length);
merge(str,start,end,mid);
}
void call(){
long *array = (long *)malloc(sizeof(long)*10);
genrand(10,array);
mergeSort(array,0,9,10);
int i=0;
for(i;i<10;i++)
printf("%ld\n",array[i]);
}
自下而上代码实现
void merge(long *str,int start ,int end,int mid){
if(start>=end || mid >=end)
return;
int i =start;
int j =mid+1;
int k =0;
long *tmp = (long *)malloc(sizeof(long)*(end-start+1));
while(i<=mid && j<=end){
if(str[i]<=str[j])
tmp[k++]=str[i++];
else
tmp[k++]=str[j++];
}
while(i<=mid)
tmp[k++]=str[i++];
while(j<=end)
tmp[k++]=str[j++];
for(i=start;i<=end;i++)
str[i]=tmp[i-start];
free(tmp);
}
void mergeGroup(long *str,int len,int gap){
int i=0;
//需要归并的总长度
int twoLen = 2*gap;
//因为数组下标以0开始,所以要-1
for(i=0;i+twoLen-1<len;i+=twoLen){
//i是起点,起点+总长度-1 为终点,起点+每一个数组的长度-1为分割点
merge(str,i,i+twoLen-1,i+gap-1);
}
//如果便利一遍后 分割点还是小于数组最后一个下标,则表示还有最后一个归并没有完成,起点为i终点为len-1
if(i+gap-1 < len-1)
merge(str,i,len-1,i+gap-1);
}
void mergeSortDownUp(long * str,int length){
int n;
if(str == NULL || length<=0)
return;
//n 可以理解为每一次归并的数组长度
for(n=1;n<length;n*=2)
mergeGroup(str,length,n);
}
void call(){
long *array = (long *)malloc(sizeof(long)*10);
genrand(10,array);
mergeSortDownUp(array,10);
int i=0;
for(i;i<10;i++)
printf("%ld\n",array[i]);
}
genrand() 和swap()函数的实现如下。
int genrand(int num,long * array ){
if (num>10000)
return 0 ;
srand((unsigned int)time(0));
int i=0;
for(i=0;i<num;i++)
array[i] = rand();
return 1;
}
void swap(long *A,long *B){
long tmp;
tmp = *A;
*A = *B;
*B = tmp;
}
运行环境:ubuntu14.04 、gcc
注:如有错误望批评指正。