前言
快速排序是一种高效的排序算法,采用"分而治之"的思想。本文将详细介绍如何在JavaScript中实现快速排序,并提供带有详细注释的代码。
快速排序原理
快速排序的核心思想是:
- 选择基准值:从数组中选择一个元素作为基准(pivot)
- 分区操作:将数组分为两部分,小于基准值的放在左边,大于基准值的放在右边
- 递归排序:对左右两部分递归地进行快速排序
JavaScript实现
以下是带有详细注释的JavaScript实现:
/**
* 快速排序函数
* @param {Array} arr 待排序数组
* @param {number} left 左边界索引
* @param {number} right 右边界索引
*/
function quickSort(arr, left = 0, right = arr.length - 1) {
// 递归终止条件:当左边界不小于右边界时,说明子数组长度为0或1,无需排序
if (left >= right) return;
// 初始化指针,考虑边界问题,所以从left-1和right+1开始
let i = left - 1;
let j = right + 1;
// 选择基准值,这里选择中间位置的元素
const pivot = arr[Math.floor((left + right) / 2)];
// 分区操作
while (i < j) {
// 从左向右找到第一个不小于基准值的元素
do {
i++;
} while (arr[i] < pivot);
// 从右向左找到第一个不大于基准值的元素
do {
j--;
} while (arr[j] > pivot);
// 如果i<j,交换这两个元素的位置
if (i < j) {
[arr[i], arr[j]] = [arr[j], arr[i]]; // ES6解构赋值实现交换
}
}
// 递归排序左子数组(从left到j)
quickSort(arr, left, j);
// 递归排序右子数组(从j+1到right)
quickSort(arr, j + 1, right);
}
// 使用示例
const array = [3, 6, 8, 10, 1, 2, 1];
console.log('排序前:', array);
quickSort(array);
console.log('排序后:', array);
代码解析
-
基准选择:我们选择数组中间位置的元素作为基准值。这有助于在大多数情况下获得较好的性能。
-
分区过程:
- 使用两个指针
i和j分别从数组两端向中间移动 i指针寻找第一个不小于基准值的元素j指针寻找第一个不大于基准值的元素- 当找到这样的元素对时,交换它们的位置
- 使用两个指针
-
递归调用:
- 分区完成后,数组被分为两部分
- 对这两部分分别递归调用快速排序
优化考虑
- 小数组优化:对于小数组(如长度小于10),插入排序可能更高效
- 随机基准:随机选择基准值可以避免最坏情况
- 三数取中法:选择第一个、中间和最后一个元素的中值作为基准
复杂度分析
-
时间复杂度:
- 最佳/平均情况:O(n log n)
- 最坏情况(已排序数组):O(n²)
-
空间复杂度:
- 最佳/平均情况:O(log n)(递归调用栈)
- 最坏情况:O(n)
总结
快速排序是一种高效的排序算法,尤其适合大数据量的排序。它的原地排序特性(只需要很小的额外空间)使其在实际应用中非常受欢迎。理解其分区过程和递归思想对于掌握算法精髓至关重要。