排序算法全解,为什么快排的时间波动特别大?

排序算法全解,为什么快排的时间波动特别大?

目录

排序算法全解,为什么快排的时间波动特别大?

一、总览与对比分析

二、快速排序

1、核心思想

2、算法特点

3、示例

三、归并排序

1、核心思想

2、算法特点

3、示例

四、堆排序

1、核心思想

2、算法特点

3、示例

五、排序方法对比与其他排序

六、总结


        作者:watermelo37

        ZEEKLOG全栈领域优质创作者、万粉博主、华为云云享专家、阿里云专家博主、腾讯云“创作之星”特邀作者、支付宝合作作者,全平台博客昵称watermelo37。

        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。



---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

排序算法全解,为什么快排的时间波动特别大?

一、总览与对比分析

        在本文中,我们将对各种排序算法进行总体比较,重点从以下几个维度展开:

  • 时间复杂度(平均、最坏、最好)
  • 空间复杂度
  • 稳定性
  • 是否原地排序
  • 是否适合大数据
  • 实际应用场景
算法最好时间复杂度平均时间复杂度最坏时间复杂度空间复杂度稳定性原地排序适用场景
快速排序O(n log n)O(n log n)O(n^2)O(log n)大多数通用场景
归并排序O(n log n)O(n log n)O(n log n)O(n)大数据、稳定需求
堆排序O(n log n)O(n log n)O(n log n)O(1)内存受限、无稳定性需求
插入排序O(n)O(n^2)O(n^2)O(1)数据基本有序、小数组
桶排序O(n+k)O(n+k)O(n^2)O(n+k)数据分布均匀
基数排序O(nk)O(nk)O(nk)O(n+k)整数或字符串排序
冒泡排序O(n)O(n^2)O(n^2)O(1)教学演示

二、快速排序

1、核心思想

        使用分治法。

        每次选择一个基准元素,将数组分成两个部分:小于基准值的放左边,大于的放右边,然后递归处理两边,直到完全结束。

2、算法特点

        不稳定排序,原地排序。大多数通用排序任务中表现优异。

  • 时间复杂度:平均O(n log n) ;最坏情况:O(n^2)
  • 空间复杂度:O(log n),递归栈空间
稳定排序:

        
当两个元素的值相等时,排序之后它们的相对顺序不会改变。

        当你排序的是多字段对象,而且希望保留“主键不变”的排序顺序时,稳定性很关键。比如先按“姓名”排,再按“成绩”稳定排序,这样姓名相同的学生仍保持之前的顺序。

原地排序:

        
排序过程中只使用常数级别的额外空间(O(1)),排序操作直接在原数组上进行,不依赖额外的数据结构。

3、示例

// 简洁,但并非原地快排 function quickSort(arr) { if (arr.length <= 1) return arr; const pivot = arr[0]; const left = arr.slice(1).filter(x => x <= pivot); const right = arr.slice(1).filter(x => x > pivot); return [...quickSort(left), pivot, ...quickSort(right)]; } // 原地快排 function quickSort(arr, low = 0, high = arr.length - 1) { if (low < high) { // 获取分区索引:pivot 已放在正确位置 const pivotIndex = partition(arr, low, high); // 递归排序 pivot 左右两部分 quickSort(arr, low, pivotIndex - 1); quickSort(arr, pivotIndex + 1, high); } return arr; // 为了链式调用方便,可选 } // 分区函数 function partition(arr, low, high) { const pivot = arr[high]; // 选最后一个元素为 pivot let i = low; // i 表示小于等于 pivot 区域的边界 for (let j = low; j < high; j++) { // 如果当前元素 <= pivot,就把它放到左边区域 if (arr[j] <= pivot) { [arr[i], arr[j]] = [arr[j], arr[i]]; // 交换 i++; // 边界右移 } } // 最后把 pivot(arr[high])放到它该在的位置 [arr[i], arr[high]] = [arr[high], arr[i]]; return i; // 返回 pivot 的最终位置 }

三、归并排序

1、核心思想

        先分解后合并,分解成唯一个体了自然就是有序的,实际是一种基于递归的排序策略。

        分解:将数组分成两半递归排序;合并:将两个有序数组合并成一个。

2、算法特点

        稳定排序,不原地排序。适用于大数据量、稳定性要求强的场景,如外部排序、大型电商列表等。

  • 时间复杂度:O(n log n)
  • 空间复杂度:O(n)

3、示例

function mergeSort(arr) { if (arr.length <= 1) return arr; const mid = Math.floor(arr.length / 2); const left = mergeSort(arr.slice(0, mid)); const right = mergeSort(arr.slice(mid)); let result = [], i = 0, j = 0; while (i < left.length && j < right.length) { result.push(left[i] <= right[j] ? left[i++] : right[j++]); } return [...result, ...left.slice(i), ...right.slice(j)]; }

四、堆排序

1、核心思想

        利用最大堆结构,每次把堆顶(最大值)放到数组末尾,重新调整堆。

2、算法特点

        不稳定排序,原地排序。适用于无需稳定性要求、空间敏感场景。

  • 时间复杂度:O(n log n)
  • 空间复杂度:O(1)

3、示例

function heapSort(arr) { const n = arr.length; // 构建大顶堆,从最后一个非叶子节点开始 for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { heapify(arr, n, i); } // 依次取出堆顶元素,放到数组末尾 for (let i = n - 1; i > 0; i--) { [arr[0], arr[i]] = [arr[i], arr[0]]; // 交换堆顶与当前尾部 heapify(arr, i, 0); // 重新对堆顶元素调整堆 } return arr; } // 维护大顶堆的堆化过程 function heapify(arr, heapSize, rootIndex) { let largest = rootIndex; const left = 2 * rootIndex + 1; const right = 2 * rootIndex + 2; // 找出三个节点中最大的那个 if (left < heapSize && arr[left] > arr[largest]) largest = left; if (right < heapSize && arr[right] > arr[largest]) largest = right; // 如果最大值不是根节点,交换并递归堆化 if (largest !== rootIndex) { [arr[rootIndex], arr[largest]] = [arr[largest], arr[rootIndex]]; heapify(arr, heapSize, largest); } } // 示例 const arr = [4, 10, 3, 5, 1]; console.log(heapSort(arr)); // 输出: [1, 3, 4, 5, 10]

五、排序方法对比与其他排序

        

        有一点需要注意,归并排序和堆排序的耗时都非常稳定,不管原始数据是整齐还是混乱,因为他们的执行流程不依赖于数据的初始顺序。但是快速排序耗时波动大,快排的性能高度依赖于“划分是否平衡”,而这个又与基准值的选择以及原始数据分布密切相关。

        相对来说,堆排序不如归并排序和快排常用,虽然堆排序的时间复杂度稳定,但在实际运行中堆的 heapify 操作涉及大量的父子节点交换,不如快排那样直接交换元素高效,且堆是树形结构,访问内存不是连续的,会导致 CPU 缓存命中率低,最后还不是稳定排序,虽然快速排序也不是稳定排序,但那是快排快啊。

        常见通用排序方法里面,只有快速排序、归并排序和堆排序的时间复杂度最优,像冒泡排序、插入排序、选择排序、希尔排序时间复杂度都要逊色一些。

        但有些排序方法,在特殊场景下的时间复杂度优于O(n log n),这里不详细介绍。

算法时间复杂度适用场景
计数排序O(n + k)整数且范围小(如 0~100)
桶排序O(n + k)分布均匀的浮点数
基数排序O(n · d)多位数或字符串,d 为位数

六、总结

        简单做一个“技术选型”的场景推荐:

  • 若数据量大,推荐 归并堆排序
  • 对性能极致要求时,快排更合适(但注意最坏 O(n²))
  • 空间敏感:选择堆排序
  • 数据几乎有序:插入排序
  • 数字范围小或分布均匀:计数/桶排序
  • 大批量整数:基数排序

        只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        其他热门文章,请关注:

        极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        Web Worker:让前端飞起来的隐形引擎

        DeepSeek:全栈开发者视角下的AI革命者

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

        测评:这B班上的值不值?在不同城市过上同等生活水平到底需要多少钱?

        通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

        TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

        通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

        深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

        前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题

      【前端实战】如何让用户回到上次阅读的位置?

        内存泄漏——海量数据背后隐藏的项目生产环境崩溃风险!如何避免内存泄漏

        MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

        JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

        高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

Read more

曝Windows 12将于今年发布?以AI为核心、NPU成「硬件门槛」,网友吐槽:“不想要的全塞进来了”

曝Windows 12将于今年发布?以AI为核心、NPU成「硬件门槛」,网友吐槽:“不想要的全塞进来了”

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 当年,微软一句“Windows 10 将是最后一个版本”的表态,让不少用户以为 Windows 进入了“只更新、不换代”的时代。但几年过去,现实却完全不同。 在 Windows 11 发布之后,如今关于 Windows 12 的传闻再次密集出现。从内部代号、代码片段,到硬件厂商的暗示与 OEM 预热标签,种种线索拼在一起,勾勒出一个明显的趋势——这不会只是一次常规升级,而更像是一次围绕 AI 的平台级重构。 更关键的是,这次争议,可能远比当年 TPM 2.0 更大。 精准卡位 Windows 10 退场的时间?

By Ne0inhk
Python热度下滑、AI能取代搜索引擎?TIOBE最新榜单揭晓!

Python热度下滑、AI能取代搜索引擎?TIOBE最新榜单揭晓!

整理 | 屠敏 出品 | ZEEKLOG(ID:ZEEKLOGnews) 日前,TIOBE 发布了最新的 3 月编程语言榜单。整体来看,本月排名变化不算大,但榜单中仍然出现了一些值得关注的小波动。  AI 工具能帮大家秒懂最新编程语言趋势? 由于 2 月天数较少,3 月的榜单整体变化有限。借着这次发布,TIOBE CEO Paul Jansen 也回应了一个最近被频繁讨论的问题:为什么 TIOBE 指数仍然依赖搜索引擎统计结果?在大语言模型流行的今天,直接询问 AI 哪些编程语言最流行,是不是更简单? 对此,Jansen 的回答是否定的。 他解释称,TIOBE 指数本质上统计的是互联网上关于某种编程语言的网页数量。而大语言模型的训练数据同样来自这些网页内容,因此从信息来源来看,两者并没有本质区别。换句话说,LLM 的判断,本质上也是建立在这些网页数据之上的。 Python 活跃度仍在下降

By Ne0inhk
“裸奔龙虾”数量已达27万只,业内人士警告;AI浪潮下,中传“砍掉”翻译等16个专业;薪资谈判破裂,三星电子8.9万人要罢工 | 极客头条

“裸奔龙虾”数量已达27万只,业内人士警告;AI浪潮下,中传“砍掉”翻译等16个专业;薪资谈判破裂,三星电子8.9万人要罢工 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * “裸奔龙虾”已高达27万只!业内人士警告:一旦黑客入侵,敏感信息一秒搬空 * 阿里云 CTO 周靖人代管千问模型一号位,刘大一恒管理更多团队 * 中国传媒大学砍掉翻译、摄影等 16 个本科专业,直言教育要面向人机分工时代 * 雷军放话:小米将很快推出 L3、L4 的驾驶 * 消息称原理想汽车智驾一号位郎咸朋具身智能赛道创业 * vivo 前产品经理宋紫薇创业,瞄准 AI 时尚Agent,获亿元融资 * MiniMax 发布龙虾新技能,股价暴涨超 23% * 薪资谈判破裂,三星电子

By Ne0inhk
一天开13个会、一个Bug要修200天!前亚马逊L7爆料:这轮大裁员,AI只是“背锅侠”

一天开13个会、一个Bug要修200天!前亚马逊L7爆料:这轮大裁员,AI只是“背锅侠”

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 过去一年,大型科技公司的裁员消息几乎从未停过。但当公司对外给出的理由越来越统一,“AI 让组织更高效”,也有越来越多内部员工开始提出另一种质疑:事情或许没那么简单。 最近,一段来自前亚马逊员工 Becky 的 YouTube 视频在开发者社区流传开来。她曾在亚马逊工作 7 年,其中 5 年担任 L7 级别的技术管理者,负责过团队年度规划(OP1)等核心管理工作——可去年,她主动离开了亚马逊。 就在最近,她的三位前同事接连被裁,其中两人还是 H-1B 签证员工,都背着房贷压力。其中一位同事忍不住给 Becky 发消息:“你去年离开的时候,是不是已经预料到会发生这些?” 对此,Becky 的回答很坦诚:她不知道具体什么时候会裁员,但她早就感觉情况不对劲了。 在她看来,这轮裁员被归因为

By Ne0inhk