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

在这里插入图片描述

🔥 个人主页:空白诗

在这里插入图片描述

文章目录

    • 一、算法原理
    • 二、算法实现
    • 三、应用场景
    • 四、优化与扩展
    • 五、总结

在这里插入图片描述

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


一、算法原理

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

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

在这里插入图片描述


二、算法实现

以下是快速排序的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. 选择基准优化:选择基准的方式可以影响排序效率。常见的优化方法包括三数取中法和随机选择法。
/**
 * 三数取中法选择基准
 * 该方法通过选择数组中的三个元素(第一个元素、中间元素和最后一个元素),
 * 并将它们进行比较,选择其中的中位数作为基准索引,以减少快速排序的最坏情况发生。
 * @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. 尾递归优化:通过尾递归优化减少栈的深度,提高效率。
/**
 * 快速排序算法(尾递归优化)
 * 该算法通过分治法将数组分为较小的子数组,递归地排序子数组。尾递归优化可以减少栈的深度,提高效率。
 * @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]

五、总结

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/793704.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue使用quill编辑器自定义附件上传方法,并根据上传附件名称生成链接

1、附件上传 需求&#xff1a; 在编辑器中上传word,pdf,excel等附件后&#xff0c;能根据上传附件的名称生成link链接&#xff0c;在展示页面能实现点击链接下载或预览附件&#xff0c;效果图如下: 实现方法&#xff1a; quill编辑器自身带有link&#xff0c;但不满足需求&…

Java---SpringBoot详解二

勤奋勤劳铸梦成&#xff0c; 晨曦微露起长征。 汗水浇灌花似锦&#xff0c; 寒窗苦读岁月明。 千锤百炼心如铁&#xff0c; 万里征途志不倾。 持之以恒终有日&#xff0c; 功成名就笑谈中。 目录 一&#xff0c;统一响应结果 二&#xff0c;三层架构 三&#xff0c;分层解耦 四…

基于html开发的在线网址导航在线工具箱源码

基于html开发的在线网址导航在线工具箱源码&#xff0c;将全部文件复制到服务器&#xff0c;入口文件是index.html 如需修改网址&#xff0c;可修改index.html 如需修改关于页面&#xff0c;可修改about里面的index页面 源码下载&#xff1a;https://download.csdn.net/down…

存储实验:Linux挂载iscsi硬盘与华为OceanStor创建LUN全流程

目录 目的环境规划实验实验流程Centos配置0. 关闭防火墙1. 设置网卡信息2. 配置路由3. iscsiadm连接存储 iSCSI LUN创建&#xff08;以华为OceanStor为例&#xff09;验证1. 验证是否成功2. 开启自动挂载 目的 实现Linux连接iscsi硬盘&#xff0c;同时实现开机自启挂载 环境规…

综合实验作业

node01&#xff1a;192.168.175.146 node02&#xff1a;192.168.175.147 【node01】 node01 与 node02 防火墙在本实验中都需要放行的服务&#xff1b; [rootlocalhost ~]# firewall-cmd --permanent --add-servicedns success [rootlocalhost ~]# firewall-cmd --permanent -…

实变函数精解【3】

文章目录 点集求导集 闭集参考文献 点集 求导集 例1 E { 1 / n 1 / m : n , m ∈ N } 1. lim ⁡ n → ∞ ( 1 / n 1 / m ) 1 / m 2. lim ⁡ n , m → ∞ ( 1 / n 1 / m ) 0 3. E ′ { 0 , 1 , 1 / 2 , 1 / 3 , . . . . } E\{1/n1/m:n,m \in N\} \\1.\lim_{n \rightar…

PGCCC|【PostgreSQL】PCA认证考试大纲#postgresql认证

PostgreSQL Certified Associate|PCA&#xff08;初级&#xff09; 学员将学会安装、创建和维护PostgreSQL数据库。学完后&#xff0c;学员可以从事PostgreSQL数据库的数据操作和管理等工作。 获证途径 参加PostgreSQL培训再考试 考试为上机考试。 PostgreSQL PCA培训考试课…

“金山-讯飞”杯2024年武汉理工大学程序设计竞赛 A. Mobiusp败走***(思维题-点双连通分量、连通性)

题目 思路来源 官方题解 题解 手玩发现&#xff0c;能换的话&#xff0c;当且仅当.和1在一个环里&#xff0c;而这就是点双连通分量 所以最优策略是先把.换到(x,y)的位置&#xff0c;然后判断.和1在不在一个环里 也就是&#xff1a; 1. 判断删掉1时&#xff0c;.和(x,y)联…

VSCode上通过C++实现单例模式

单例模式实际上就是为了确保一个类最多只有一个实例&#xff0c;并且在程序的任何地方都可以访问这个实例&#xff0c;也就是提供一个全局访问点&#xff0c;单例对象不需要手动释放&#xff0c;交给系统来释放就可以了&#xff0c;单例模式的设计初衷就是为了在整个应用程序的…

基于扩散的生物打印策略,控制可打印性和结构特性

基于扩散的生物打印策略&#xff0c;控制可打印性和结构特性 在生物打印中&#xff0c;将生物材料和细胞按特定设计逐层堆积&#xff0c;构建具有复杂结构和功能的三维组织结构。微挤出生物打印是最常用的方法&#xff0c;其核心是生物墨水&#xff0c;它由聚合物材料和细胞组…

Go语言入门之Map详解

Go语言入门之Map详解 1.基础定义 map是一个无序的&#xff0c;k-v键值对格式的集合 &#xff08;1&#xff09;特点 类型特点&#xff1a;map为引用类型&#xff0c;所以在函数中更新value值会永久改变顺序特点&#xff1a;map的遍历是无序的&#xff0c;因为底层是哈希表&am…

[Linux][Shell][Shell逻辑控制]详细讲解

目录 1.if 判断1.if-then2.if-then-else3.elif4.case5.实际上手 2.条件测试0.事前说明1.test 命令2.[]3.双括号1.(())2.[[]] 4.实际上手 3.循环1.for2.while3.until命令4.控制循环1.break2.continue 5.处理循环的输出 1.if 判断 1.if-then 语法&#xff1a;if command thenco…

ARM功耗管理标准接口之SCMI

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理有哪些标准接口&#xff1f;ACPI&PSCI&SCMI&#xff1f; Advanced Configuration and Power Interface Power State Coordination Interface System Control and Management Interface 下图示例说明了实现…

MongoDB教程(一):Linux系统安装mongoDB详细教程

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、Ubuntu…

昇思25天学习打卡营第23天|基于MindSpore通过GPT实现情感分类

1. 学习内容复盘 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面mindspore的版本号 !pip uninstall mindspore -y !pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore2.2.14 I…

一文入门【NestJs】Modules

&#x1f6a9;引言 在探索NestJS的生态系统时&#xff0c;理解模块&#xff08;Modules&#xff09;的概念是至关重要的第一步。NestJS&#xff0c;作为一个基于Node.js的现代框架&#xff0c;借鉴了Angular的模块化设计思路&#xff0c;为开发者提供了一种优雅的方式来组织和…

jenkins打包java项目报错Error: Unable to access jarfile tlm-admin.jar

jenkins打包boot项目 自动重启脚本失败 查看了一下项目日志报错&#xff1a; Error: Unable to access jarfile tlm-admin.jar我检查了一下这个配置&#xff0c;感觉没有问题&#xff0c;包可以正常打&#xff0c; cd 到项目目录下面&#xff0c;手动执行这个sh脚本也是能正常…

vue中el-table单元格复制功能

一、单页面中使用 1.在el-table上绑定单击事件 cell-click“copyText” 或双击事件 cell-dblclick“copyText” 注&#xff1a;cell-dblclick函数有四个参数&#xff0c;分别是row, column, cell, event&#xff1b; row&#xff1a;可看到被其操作单元格所在行的所有的数据&…

电力需求预测挑战赛笔记 Taks1 跑通baseline

#AI夏令营 #Datawhale #夏令营 赛题 一句话介绍赛题任务可以这样理解赛题&#xff1a; 【训练时序预测模型助力电力需求预测】 电力需求的准确预测对于电网的稳定运行、能源的有效管理以及可再生能源的整合至关重要。 赛题任务 给定多个房屋对应电力消耗历史 N 天的相关序列数…

广度优先(BFS)

先看一道简单的题&#xff0c;迷宫问题&#xff1a; 洛谷P1746 离开中山路&#xff1a;P1746 离开中山路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<iostream> #include<cstring> #include<queue> #include <utility> #define N 1002 …