【算法】归并排序

124 阅读2分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

我们再来回顾下经典的排序算法有哪些:

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 希尔排序
  • 桶排序
  • 归并排序
  • 快速排序
  • 计数排序

本篇文章准备聊聊 归并排序 的原理,废话不多说,开搞!

ppx.jpg

什么是归并排序

首先引用下百度百科上对其的定义

归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序

官方的说法总是文绉绉的,不太便于理解,这里给下我自己的定义:

归并排序就是一种利用“分治”思想进行排序的方式,它先将原始的数组不断进行 拆分,直到不可拆为止,然后反向再进行 归并,归并的过程就是不断将两个子序列进行 合并排序,最终使整个数组达到有序

666.jpg

举个栗子🌰

光从定义上,其实还是不能很直观的感受其本质,所谓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]

我们来分析下代码

  1. 在sort函数内,首先利用数组的长度将其一分为二,这个函数做的事情其实就是上文提到的 拆分
  2. 递归地调用sort方法,将其左右子序列不断拆分
  3. 递归的终止条件为子序列长度小于2(这个不用我解释了吧😄)
  4. merge函数的作用其实就是上文提到的 归并,它具体做的事情就是去合并两个有序数组,使其合并结果也保持有序
  5. 当归并完最后一组子序列后,整个数组达到有序态

niubi2.jpg

结语

其实归并排序的原理很简单,就是一个先拆分后归并的过程,但自己之前其实一直没研究这个算法,只是知道有这种排序方式,通过最近的研究学习,我自己已经掌握其原理了,那么看完文章的你呢?😄