排序之快速排序 | 刷题打卡

168 阅读2分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述

使用快速排序对一个非有序数组进行升序的排序。

示例:

输入:[5, 8, 6, 3, 4, 7, 1, 2]
输出:[1, 2, 3, 4, 5, 6, 7, 8]

二、思路分析

快速排序比冒泡排序和选择排序的性能都好,是一种可以在实际项目中应用的排序算法。

从数组中任意选择一个基准;
所有比基准小的元素放在基准的前面(左边);
基准大的元素放在基准的后面(右边);
那么此时至少基准这个数是找到了它的位置;
这个操作叫做分区。

然后以此类推,使用递归的方式,不断对分区后的 左分区 和 右分区 继续进行分区操作,直到无法分区(也就是只有一位数的数组)的时候,排序就完成了,因为一位数的数组是有序的。

// 第一轮 - 以 5 为基准
 ^
[5, 8, 6, 3, 4, 7, 1, 2]

[3, 4, 1, 2] 5 [8, 6, 7]

// 第二轮 - 以 3、8 为基准
 ^              ^
[3, 4, 1, 2] 5 [8, 6, 7]

[1, 2] 3 [4] 5 [6, 7] 8

// 第三轮 - 以 1、4、6 为基准
 ^        ^     ^
[1, 2] 3 [4] 5 [6, 7] 8

1 [2] 3 4 5 6 [7] 8

// 第四轮 - 以 2、7 为基准
   ^           ^
1 [2] 3 4 5 6 [7] 8

1 2 3 4 5 6 7 8

三、AC 代码

Array.prototype.quickSort = function () {
    const rec = array => {
        if(array.length <= 1) return array // 边界
        
        const mid = array[0] // 基准
        const left = [] // 比基准小的
        const right = [] // 比基准大的

        for(let i = 1; i < array.length; i++) {
            const d = array[i]
            mid < d
                ? right.push(d) // 比基准大的
                : left .push(d) // 比基准小的
        }
        
        // 递归 & 展开 | 并返回
        return [...rec(left), mid, ...rec(right)]
    }
    
    // 获取到排序后的数组
    const newArray = rec(this)
    
    // 不修改原数组的指向的情况下,更新内容
    newArray.forEach((v, i) => this[i] = v)
}

const arr = [5, 8, 6, 3, 4, 7, 1, 2]
arr.quickSort()

console.log(arr) // 1 2 3 4 5 6 7 8

四、总结

排序在项目当中是非常常见的场景,所以排序算法是每个程序员都必须掌握并且熟练运用的算法之一。

快速排序算法的特点就是根据基准值对数组进行分区,然后对分区出来的数组再进行分区,直到为一位的有序数组,然后将其组合起来。

其实只要弄清楚了 [...rec(left), mid, ...rec(right)] 这一句的作用,以及如何分区获得 leftright,那么基本上就能明白快速排序算法的实现逻辑是什么。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情