javascript算法系列——排序5:归并排序

核心思想:分治&递归

递归大家应该都知道,那么分治是什么意思呢?分治即分而治之:先将问题分成一些小的问题然后递归求解,再将分的阶段得到的各答案"修补"在一起。

来看下怎么把分治的思想应用到排序上:

先将数组按照len / 2 的长度递归划分为2个数组,直到数组长度=1(分),然后再讲划分后的小数组合并成有序的数组(治)。
在这里插入图片描述

javascript代码实现:
const merge_sort = (arr) => {
	const tempArr = [];
	const left_i = 0;
	const right_i = arr.length - 1;
	divide(tempArr, arr, left_i, right_i)
	return arr;
}

const divide = (tempArr, arr, left, right) => {
	// 如果只有一个元素.则不需要继续被划分了
	if (left < right) {
		// 找到中间点
		const mid = Math.floor((right + left) / 2);
		// 递归左半区域
		divide(tempArr, arr, left, mid);
		// 递归右半区域
		divide(tempArr, arr, mid + 1, right);
		// 排序并合并
		merge(tempArr, arr, left, mid, right);
	}
}


const merge = (tempArr, arr, left, mid, right) => {
	// 左半区域第一个未排序的数的下标
	let l_pos = left;
	// 左半区域第一个未排序的数的下标
	let r_pos = mid + 1;
	// 临时数组元素的下标
	let pos = left;

	// 合并
	while (l_pos <= mid && r_pos <= right) {
		if (arr[l_pos] < arr[r_pos]) {
			// 左半区的第一个元素更小,则交换
			// tempArr[pos++] = arr[l_pos++]
			// 等同于
			tempArr[pos] = arr[l_pos]
			pos++;
			l_pos++;
		} else {
			tempArr[pos++] = arr[r_pos++];
		}
	}

	// 这里要么只有左半区域有剩余的元素,要么只有右半区域有剩余的元素,不会存在同时进入的情况
	//(即下面两个while只可能会进去一个)
	
	// 合并左半区域剩余的元素
	while(l_pos <= mid) {
		tempArr[pos++] = arr[l_pos++]
	}

	// 合并右半区域剩余的元素
	while(r_pos <= right) {
		tempArr[pos++] = arr[r_pos++]
	}

	// 把临时数组中合并后的元素复制回原数组
	while (left <= right) {
		arr[left] = tempArr[left]
		left++
	}
}

关键点:在入口函数中就给该程序分配一个临时空间,用于在每次递归中将排好序的数组合并。

复杂度分析:

空间复杂度:因为分配了一个长度为n的临时空间,不再是原地排序,所以空间复杂度为O(n);
时间复杂度:每一层归并的时间复杂度为O(n),归并层数最大为O( l o g n + 1 {log_{n}}+1 logn+1),两者相乘,省去常数,所以时间复杂度是O( n l o g n n{log_{n}} nlogn)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值