本篇文章参考借鉴了以下文章和极客时间的数据结构与算法一文,若涉及侵权,请联系我删除。
前言
之前的博客里面我们一块学习了,冒泡排序,插入排序,选择排序,这三种排序算法,它们的时间复杂度都是O(n2),适用于小规模数据的排序,本篇文章,我们一块来学习下归并排序。适用于大规模数据。
没看过之前文章的小伙伴可以先了解一下
核心思想
归并排序的核心思想是 分治思想 ,非常巧妙。我们可以借鉴这个思想,来解决非排序问题,比如:如何在O(n)的时间复杂度内查找一个无需数组的第 K 大元素?,这就用到了归并排序。
归并排序原理
归并排序的实现原理还是比较简单的,如果要排序一个数组,我们先把数组从中间分成前后两个部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就有序了。

分治,顾名思义就是分而治之,将一个大问题分解成小的子问题来解决。小问题解决了,大问题也就解决了。
从刚才的描述中可以看出,分治思想跟递归很像。是的,分治算法一般都是用递归实现的。分治是一种解决问题的处理思想,递归是一种编程技巧,这两者并不冲突。分治算法的思想我们放到后面的章节来梳理,现在不展开讨论,本篇文章重点还是排序算法。
如何实现归并排序
如何用递归来实现归并排序?
首先,递归代码的技巧是分析得出递推公式,找到终止条件,最后将递推公式翻译成递推代码。所以一起看看如何写出递推公式。
递推公式:
margin_sort(p...r) = merge(merge_sort(p...q), merge_sort(q+1...r))
终止条件:
p >= r不用再继续分了。
该递推公式仔细观察就会发现:margin_sort(p...r)表示给下标从 p 到 r 之间的数组排序。现在将这个排序问题转化成两个子问题,margin_sort(p...q)和margin_sort(q+1...r),其中 q 是 p 和 r 的中间位置,也就是(p + r)/2。
当下标从 p 到 q 和从 q + 1 到 r 这两个子数组都排序好之后,我们再将两个有序的子数组合并在一起,这样下标从 p 到 r 之间的数据也就好排序了。
有了递推公式,下一步就是转换成代码了,各位请看:
//归并排序算法
function mergeSort(arr) {
mergeSortFn(arr, 0, arr.length - 1)
}
//递归调用函数
function mergeSortFn(arr, p, r) {
//递归终止条件
if (p >= r) return;
//取 p 到 r 之间的中位数 q
let q = parseInt((p + r) / 2);
//分治递归
mergeSortFn(arr, p, q

最低0.47元/天 解锁文章
2084

被折叠的 条评论
为什么被折叠?



