归并排序--自上而下和自下而上两种方法的实现

归并排序思想

自上而下的递归

对一个数组(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

注:如有错误望批评指正。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值