本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述
使用快速排序对一个非有序数组进行升序的排序。
示例:
输入:[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)] 这一句的作用,以及如何分区获得 left 和 right,那么基本上就能明白快速排序算法的实现逻辑是什么。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情