JavaScript实现快速排序算法详解

252 阅读3分钟

前言

快速排序是一种高效的排序算法,采用"分而治之"的思想。本文将详细介绍如何在JavaScript中实现快速排序,并提供带有详细注释的代码。

快速排序原理

快速排序的核心思想是:

  1. 选择基准值:从数组中选择一个元素作为基准(pivot)
  2. 分区操作:将数组分为两部分,小于基准值的放在左边,大于基准值的放在右边
  3. 递归排序:对左右两部分递归地进行快速排序

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);

代码解析

  1. 基准选择:我们选择数组中间位置的元素作为基准值。这有助于在大多数情况下获得较好的性能。

  2. 分区过程

    • 使用两个指针ij分别从数组两端向中间移动
    • i指针寻找第一个不小于基准值的元素
    • j指针寻找第一个不大于基准值的元素
    • 当找到这样的元素对时,交换它们的位置
  3. 递归调用

    • 分区完成后,数组被分为两部分
    • 对这两部分分别递归调用快速排序

优化考虑

  1. 小数组优化:对于小数组(如长度小于10),插入排序可能更高效
  2. 随机基准:随机选择基准值可以避免最坏情况
  3. 三数取中法:选择第一个、中间和最后一个元素的中值作为基准

复杂度分析

  • 时间复杂度:

    • 最佳/平均情况:O(n log n)
    • 最坏情况(已排序数组):O(n²)
  • 空间复杂度:

    • 最佳/平均情况:O(log n)(递归调用栈)
    • 最坏情况:O(n)

总结

快速排序是一种高效的排序算法,尤其适合大数据量的排序。它的原地排序特性(只需要很小的额外空间)使其在实际应用中非常受欢迎。理解其分区过程和递归思想对于掌握算法精髓至关重要。