归并排序就有点大事化小的感觉,把一个复杂的问题,拆解成一个很简单问题的集合的过程。
在数组排序中,由于排序的复杂度会随着元素的增多会变得难起来,如果凭借肉眼是很难排好序的,但如果数组中只有两个元素,我们可以很快的排好序。
归并的思路:
[9, 6, 5, 4, 3, 7, 5, 2, 10] 像这样的数组,可以像下面分解,首先把数组一分为二:
[9, 6, 5, 4, 3], [7, 5, 2, 10] 发现还是很难,继续拆分
[9, 6, 5], [4, 3] 和 [7, 5],[2, 10] 这样子基本上可以一眼看出来了,但由于是程序,我们把数组的大小都控制 1 个以内,足够简单
[9, 6], [5], [4], [3] 和 [7], [5], [2], [10]
[9], [6], [5], [4], [3], [7], [5], [2], [10]
现在已经分解完成了,可以合并了,对于我们来说就很简单了。
1) [9], [6] [9, 6]
2) [9, 6], [5] [9, 6, 5]
3) [4], [3] [4, 3]
4) [7], [5] [7, 5]
5) [2], [10] [10, 2]
6) [9, 6, 5], [4, 3] [9, 6, 5, 4, 3]
7) [7, 5], [10, 2] [10, 7, 5, 2]
8) [9, 6, 5, 4, 3], [10, 7, 5, 2] [10, 9, 7, 6, 5, 5, 4, 3, 2]
全部都是我写完的,因为经过拆分以后就变得很简单了,当然这样的数组即便没有这个也很简单。程序执行的大致就相当于上面,我们先实现拆分的函数。
const mergeSort = (arr) => {
// 先写结束的条件
const len = arr.length;
// 如果数组的个数只有一个,那么就返回就像上面拆分的最后一步的
if (len < 2) {
return arr;
}
// 由于 js 这样除会得到小数,所以需要使用这个函数取整,采用向下取整就可以,其实都可以的
const middle = Math.round(len/2);
// 拆分数组,拆分成左右两部分
const leftArr = arr.slice(0, middle);
const rightArr = arr.slice(middle);
// 然后把拆分的数组合并并返回,合并的函数 merge 还没实现
return merge(mergeSort(leftArr), mergeSort(rightArr));
}
现在我们再看数组合并:
// 合并传入的两个数组并排序,我们默认按大到小
const merge = (leftArr, rightArr) => {
// 由于重点是拆分思想,这里的合并我就简单实现了
const arr = [...leftArr, ...rightArr]
// 其实这里使用 “双指针” 法来合并比较好
return arr.sort((a, b) => b - a)
}
由于我是复习所以一看就明白了,如果你是第一次接触,可以去网上看相关的演示图,更好的理解,下面是可以看各种排序算法的演示图的网址:排序演示。