排序算法 — 归并排序

归并排序(Merge Sort)

核心:分治思想+递归策略

将待排序序列不断划分为左、右两部分,然后将左、右部分分别排序后再进行合并,最后逐级合并得到有序序列。

基本思路(升序排序)

  1. 将待排序序列尽可能均分为左、右两个部分
  2. 将左部分继续划分,直到只有一个元素为止
  3. 将右部分继续划分,直到只有一个元素为止
  4. 归并各级的左、右两部分(分别取左、右部分的元素按照升序合并为一个新序列)
  5. 逐级归并直到所有的左、右部分合并完成

过程模拟

代码参考

//合并函数
void merge(int arr[],int tmp[],int left,int mid,int right) {
	//标记左半区第一个未排序的元素
	int l_pos=left;
	//标记右半区第一个未排序的元素
	int r_pos=mid+1;
	//临时数组元素下标
	int pos=left;
	//合并
	while(l_pos <= mid && r_pos <= right) {
		//取左、右半区较小的元素
		if(arr[l_pos] < arr[r_pos]) {
			tmp[pos++]=arr[l_pos++];
		} else {
			tmp[pos++]=arr[r_pos++];
		}
	}
	//合并左半区剩余的元素
	while(l_pos <= mid) {
		tmp[pos++]=arr[l_pos++];
	}
	//合并右半区剩余的元素
	while(r_pos <= right) {
		tmp[pos++]=arr[r_pos++];
	}
	//临时数组中合并后的元素复制为原数组
	while(left <= right) {
		arr[left] = tmp[left];
		left++;
	}
}

//递归划分函数
void mSort(int arr[],int tmp[],int left,int right) {
	//只有一个元素,序列有序,不需要继续划分
	if(left==right) return ;
	//多个元素
	int mid=(left+right)/2; //找中间点
	mSort(arr,tmp,left,mid); //递归划分左半区
	mSort(arr,tmp,mid+1,right); //递归划分右半区
	merge(arr,tmp,left,mid,right);  //合并
}

//归并排序入口函数
void MergeSort(int arr[],int n) { //数组a,数组a的长度n
	//辅助数组,分配存储空间
	int *tmp=(int*)malloc(n*sizeof(int));
	if(tmp) { //分配内存成功
		mSort(arr,tmp,0,n-1);//递归划分
		free(tmp);//释放内存
	} else { //分配内存失败
		cout <<"error";
	}
}

复杂度

时间复杂度:O(n*log n),对与规模为n的问题,每一层合并的复杂度为O(n),一共进行log n层的划分

空间复杂度:O(n),合并n个元素需要一个大小为n的辅助空间

稳定性

稳定的排序算法,在比较和合并过程中,相同元素排序前后的相对次序不发生改变。

特点

  1. 归并排序的时间复杂度O(n*log n),这是基于比较的排序算法所能达到的最高效率
  2. 需要较多的辅助空间
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值