本文正在参加「金石计划 . 瓜分6万现金大奖」
我们再来回顾下经典的排序算法有哪些:
- 冒泡排序
- 选择排序
- 插入排序
- 希尔排序
- 桶排序
- 归并排序
- 快速排序
- 计数排序
本篇文章准备聊聊 归并排序 的原理,废话不多说,开搞!
什么是归并排序
首先引用下百度百科上对其的定义
归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序
官方的说法总是文绉绉的,不太便于理解,这里给下我自己的定义:
归并排序就是一种利用“分治”思想进行排序的方式,它先将原始的数组不断进行 拆分,直到不可拆为止,然后反向再进行 归并,归并的过程就是不断将两个子序列进行 合并排序,最终使整个数组达到有序
举个栗子🌰
光从定义上,其实还是不能很直观的感受其本质,所谓talk is cheap,show me the code,废话不多说,上代码
var a = [2,22,331,21312,213,4324,645,34,8768]
function sort(arr) {
if(arr.length < 2) return arr
let mid = Math.floor(arr.length / 2)
const left = arr.slice(0,mid)
const right = arr.slice(mid,arr.length)
return merge(sort(left),sort(right))
}
function merge(left,right) {
const res = []
for(let l = 0,r = 0,index = 0;index < left.length + right.length;index++) {
if(l >= left.length) {
res.push(right[r++])
}else if(r >= right.length) {
res.push(left[l++])
}else if(left[l] >= right[r]) {
res.push(right[r++])
}else {
res.push(left[l++])
}
}
return res
}
sort(a) => [2, 22, 34, 213, 331, 645, 4324, 8768, 21312]
我们来分析下代码
- 在sort函数内,首先利用数组的长度将其一分为二,这个函数做的事情其实就是上文提到的 拆分
- 递归地调用sort方法,将其左右子序列不断拆分
- 递归的终止条件为子序列长度小于2(这个不用我解释了吧😄)
- merge函数的作用其实就是上文提到的 归并,它具体做的事情就是去合并两个有序数组,使其合并结果也保持有序
- 当归并完最后一组子序列后,整个数组达到有序态
结语
其实归并排序的原理很简单,就是一个先拆分后归并的过程,但自己之前其实一直没研究这个算法,只是知道有这种排序方式,通过最近的研究学习,我自己已经掌握其原理了,那么看完文章的你呢?😄