【JavaScript 算法】快速排序:高效的排序算法


🔥 个人主页:空白诗

文章目录

快速排序(Quick Sort)是一种高效的排序算法,通过分治法将数组分为较小的子数组,递归地排序子数组。快速排序通常比其他 O(n log n) 算法表现更好,因为它的内部循环可以在大多数架构上被有效地实现。本文将详细介绍快速排序算法的原理、实现及其应用。


一、算法原理

快速排序通过以下步骤实现:

  1. 选择基准:从数组中选择一个元素作为基准(pivot)。
  2. 划分数组:将数组分为两部分,一部分的元素都小于基准,另一部分的元素都大于基准。
  3. 递归排序:对划分后的两部分分别进行快速排序。
  4. 合并结果:将排序好的两部分合并,得到最终的排序结果。

二、算法实现

以下是快速排序的JavaScript实现:

javascript 复制代码
/**
 * 快速排序算法
 * @param {number[]} arr - 需要排序的数组
 * @return {number[]} - 排序后的数组
 */
function quickSort(arr) {
  if (arr.length <= 1) {
    return arr; // 基础情况:数组为空或只有一个元素
  }
  
  const pivot = arr[Math.floor(arr.length / 2)]; // 选择基准元素
  const left = [];
  const right = [];
  
  // 将数组分为小于基准和大于基准的两部分
  for (let i = 0; i < arr.length; i++) {
    if (i === Math.floor(arr.length / 2)) continue; // 跳过基准元素
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  
  // 递归排序并合并结果
  return quickSort(left).concat([pivot], quickSort(right));
}

// 示例
const arr = [3, 6, 8, 10, 1, 2, 1];
const sortedArr = quickSort(arr);
console.log(sortedArr); // 输出: [1, 1, 2, 3, 6, 8, 10]

三、应用场景

  1. 大规模数据排序:快速排序在处理大规模数据时表现优秀。
  2. 需要高效排序的场景:快速排序通常比其他排序算法更快,适用于需要高效排序的场景。
  3. 多种数据类型排序:快速排序可以排序各种数据类型,如数字、字符串等。

四、优化与扩展

  1. 选择基准优化:选择基准的方式可以影响排序效率。常见的优化方法包括三数取中法和随机选择法。
javascript 复制代码
/**
 * 三数取中法选择基准
 * 该方法通过选择数组中的三个元素(第一个元素、中间元素和最后一个元素),
 * 并将它们进行比较,选择其中的中位数作为基准索引,以减少快速排序的最坏情况发生。
 * @param {number[]} arr - 数组
 * @return {number} - 基准索引
 */
function medianOfThree(arr) {
  const mid = Math.floor(arr.length / 2); // 计算中间索引
  const a = arr[0]; // 数组第一个元素
  const b = arr[mid]; // 数组中间元素
  const c = arr[arr.length - 1]; // 数组最后一个元素
  
  // 比较三个元素,返回中位数对应的索引
  if ((a > b) !== (a > c)) return 0; // 如果 a 既不是最大也不是最小,返回 0
  if ((b > a) !== (b > c)) return mid; // 如果 b 既不是最大也不是最小,返回 mid
  return arr.length - 1; // 否则返回最后一个元素的索引
}
  1. 尾递归优化:通过尾递归优化减少栈的深度,提高效率。
javascript 复制代码
/**
 * 快速排序算法(尾递归优化)
 * 该算法通过分治法将数组分为较小的子数组,递归地排序子数组。尾递归优化可以减少栈的深度,提高效率。
 * @param {number[]} arr - 需要排序的数组
 * @return {number[]} - 排序后的数组
 */
function quickSortTailRecursive(arr) {
  /**
   * 分区函数
   * 该函数选择一个基准元素,并将数组分为两部分,一部分小于基准,另一部分大于基准
   * @param {number[]} arr - 需要排序的数组
   * @param {number} left - 左边界索引
   * @param {number} right - 右边界索引
   * @return {number} - 分区索引
   */
  function partition(arr, left, right) {
    const pivot = arr[Math.floor((left + right) / 2)]; // 选择中间元素作为基准
    let i = left; // 初始化左指针
    let j = right; // 初始化右指针

    // 左右指针向中间移动,进行分区操作
    while (i <= j) {
      while (arr[i] < pivot) i++; // 左指针右移,直到找到大于等于基准的元素
      while (arr[j] > pivot) j--; // 右指针左移,直到找到小于等于基准的元素
      if (i <= j) {
        // 交换左右指针所指向的元素
        [arr[i], arr[j]] = [arr[j], arr[i]];
        i++; // 左指针右移
        j--; // 右指针左移
      }
    }
    return i; // 返回分区索引
  }

  /**
   * 排序函数
   * 递归地对数组进行排序
   * @param {number[]} arr - 需要排序的数组
   * @param {number} left - 左边界索引
   * @param {number} right - 右边界索引
   */
  function sort(arr, left, right) {
    if (left >= right) return; // 基础情况:子数组长度为0或1时,停止递归

    const index = partition(arr, left, right); // 获取分区索引
    sort(arr, left, index - 1); // 递归排序左子数组
    sort(arr, index, right); // 递归排序右子数组
  }

  sort(arr, 0, arr.length - 1); // 初始调用排序函数,排序整个数组
  return arr; // 返回排序后的数组
}

// 示例
const arr = [3, 6, 8, 10, 1, 2, 1];
const sortedArrTailRecursive = quickSortTailRecursive(arr);
console.log(sortedArrTailRecursive); // 输出: [1, 1, 2, 3, 6, 8, 10]

五、总结

快速排序是一种高效的排序算法,通过分治法将数组分为较小的子数组,递归地排序子数组。理解和掌握快速排序算法对于处理大规模数据和优化程序性能都具有重要意义。希望本文对你理解和应用快速排序有所帮助。


相关推荐
武子康9 分钟前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
fruge11 分钟前
纯css制作声波扩散动画、js+css3波纹催眠动画特效、【css3动画】圆波扩散效果、雷达光波效果完整代码
javascript·css·css3
neter.asia20 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
passer__jw76738 分钟前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
光影少年40 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
Ocean☾44 分钟前
前端基础-html-注册界面
前端·算法·html
Rattenking44 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
顶呱呱程序1 小时前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
爱吃生蚝的于勒1 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~1 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio