排序系列之归并排序,思路 + js 写法!

131 阅读1分钟

引言

什么是归并排序?归并排序是一种基于分治法的排序算法,排序长度为 n 的数组,其实就是排序两个长度为 n/2 的子数组,然后合并这两个排序的子数组,于是整个数组也就排序完了。

代码演示

tips:根据上面的思路我们可以有以下逻辑

const arr = [1, 2, 6, 7, 8, 3, 12, 9]

function mergeSort(arr) {
    // base case
    if (arr.length < 2) return arr;

    const center = Math.floor(arr.length/2);
    const left = arr.slice(0, center);
    const right = arr.slice(center);
    
    mergeSort(left) // 不断地切割数组
    mergeSort(right) // 不断地切割数组
}

思考:这份代码只做了切割吧?那么我们还需要一个合并的过程

const arr = [1, 2, 6, 7, 8, 3, 12, 9]

console.log(mergeSort(arr));

function mergeSort(arr) {
    // base case
    if (arr.length < 2) return arr;

    const center = Math.floor(arr.length/2);
    const left = arr.slice(0, center);
    const right = arr.slice(center);
    
    // 切割合并
    return merge(mergeSort(left), mergeSort(right))
}

// 合并逻辑
function merge(left, right) {
    let result = []
    while(left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift())
        } else {
            result.push(right.shift())
        }
    }

    if (left.length) {
        result = [...result, ...left]
    } 

    if (right.length) {
        result = [...result, ...right]
    }

    return result
}

合并过程解析

image.png

说明:(a)合并相邻的长度为1的子数组得到排序的长度为2的子数组;(b)合并相邻的长度为2的子数组得到排序的长度为4的子数组;(c)合并相邻的长度为4的子数组得到排序的长度为8的数组