当前位置: 首页 > news >正文

三大基本排序算法:冒泡排序、直接插入排序、直接选择排序

三大基本排序算法:冒泡排序、直接插入排序、直接选择排序

冒泡排序、直接插入排序和直接选择排序是排序算法中最基础的三种,虽然时间复杂度都是 O(n²),但它们各自的思想、实现细节和适用场景有着本质区别。本文从算法思想、代码实现、复杂度分析到稳定性逐一拆解,适合初学者建立对排序算法的系统认知。


冒泡排序

算法思想

冒泡排序的核心是"相邻比较、逐轮冒泡":每一轮从数组头部开始,依次比较相邻的两个元素,如果顺序不对就交换它们。一轮下来,当前未排序部分的最大值就会被"推"到它应该在的位置——就像气泡从水中浮出一样。

具体步骤

  1. 从第一个元素开始,依次比较相邻的两个元素arr[j]arr[j+1]
  2. 如果arr[j] > arr[j+1](升序),则交换它们。
  3. 每一轮遍历后,未排序部分的最大元素被放到了正确位置(当前轮的末尾)。
  4. 下一轮缩小范围,继续对剩余元素重复上述过程。
  5. 如果某一轮没有发生任何交换,说明数组已经有序,可以提前结束。

以一个数组[5, 3, 8, 1, 2]为例,第一轮冒泡过程:

初始:[5, 3, 8, 1, 2] 5>3 交换 → [3, 5, 8, 1, 2] 5<8 不换 → [3, 5, 8, 1, 2] 8>1 交换 → [3, 5, 1, 8, 2] 8>2 交换 → [3, 5, 1, 2, 8] ← 8 归位

代码实现

voidswap(int*a,int*b){inttmp=*a;*a=*b;*b=tmp;}voidBubbleSort(int*arr,intn){for(inti=0;i<n;i++){intflag=0;// 每轮重置,标记是否发生交换for(intj=0;j<n-i-1;j++){if(arr[j]>arr[j+1]){swap(&arr[j],&arr[j+1]);flag=1;}}if(flag==0)// 本轮没有交换,已经有序{break;}}}

优化点flag变量用于检测某一轮是否发生了交换。如果没有发生交换,说明数组已经有序,可以提前结束循环。这使得最好情况下(数组已经有序)时间复杂度降为 O(n)。

复杂度与稳定性

指标说明
最好时间复杂度O(n) — 数组已经有序,一轮扫描后 flag=0 直接退出
最坏时间复杂度O(n²) — 数组逆序,每轮都要交换
平均时间复杂度O(n²)
空间复杂度O(1) — 原地排序,仅用常量级额外空间
稳定性稳定— 只有arr[j] > arr[j+1]时才交换,相等元素不会互换位置

直接插入排序

算法思想

直接插入排序模拟的是"打扑克牌时整理手牌"的过程:手里已经有一部分排好序的牌(有序序列),每拿到一张新牌(待插入元素),就从后往前扫描已排序部分,找到合适的位置插入。

具体步骤

  1. 将第一个元素视为已排序序列。
  2. 取出下一个元素作为待插入元素tmp
  3. 在已排序序列中从后向前扫描,如果已排序元素大于tmp,则将该元素后移一位。
  4. 找到第一个不大于tmp的位置,将tmp插入其后。
  5. 重复步骤 2-4,直到所有元素处理完毕。

以数组[5, 3, 8, 1, 2]为例:

i=0: [5 | 3, 8, 1, 2] 5视为已排序 i=1: [3, 5 | 8, 1, 2] 3插入到5前面 i=2: [3, 5, 8 | 1, 2] 8不变,已在正确位置 i=3: [1, 3, 5, 8 | 2] 1一直移动到最前面 i=4: [1, 2, 3, 5, 8] 2插入到3前面

代码实现

voidInsertSort(int*arr,intn){for(inti=0;i<n-1;i++){intend=i;// 已排序部分的最后一个位置inttmp=arr[end+1];// 待插入的元素while(end>=0){if(arr[end]>tmp){arr[end+1]=arr[end];// 比tmp大的元素后移end--;}else{break;// 找到插入位置}}arr[end+1]=tmp;// 插入到正确位置}}

关键细节

  • 外层循环条件是i < n - 1,因为当i = n-2时取arr[n-1]作为最后一个待插入元素。
  • while循环的终止条件是end >= 0,当end减到-1时说明tmp比所有已排序元素都小,插入到数组最前面。

复杂度与稳定性

指标说明
最好时间复杂度O(n) — 数组已经有序,内层 while 每次只比较一次就 break
最坏时间复杂度O(n²) — 数组逆序,每个元素都要移到最前面
平均时间复杂度O(n²)
空间复杂度O(1) — 原地排序
稳定性稳定— 只有arr[end] > tmp时才后移,相等元素不跨越

直接选择排序

算法思想

直接选择排序的核心是"每轮选出最值,放到两端":每一轮在未排序区间中找到最小值和最大值,将最小值放到区间开头,最大值放到区间末尾,然后缩小区间继续。

本文展示的是双向优化版本,每轮同时选出最小值和最大值,比传统单向选择排序少一半的遍历轮数。

具体步骤

  1. 设定左右边界begin = 0end = n - 1
  2. [begin, end]范围内遍历,记录最小值下标mini和最大值下标maxi
  3. arr[mini]arr[begin]交换,将arr[maxi]arr[end]交换。
  4. begin++end--,缩小区间。
  5. 重复步骤 2-4,直到begin >= end

以数组[5, 3, 8, 1, 2]为例:

[5, 3, 8, 1, 2] begin=0, end=4, mini=3(值1), maxi=2(值8) 交换mini↔begin, maxi↔end → [1, 3, 2, 5, 8] [1, 3, 2, 5, 8] begin=1, end=3, mini=2(值2), maxi=3(值5) 交换mini↔begin, maxi↔end → [1, 2, 3, 5, 8] begin=2, end=2 → 结束

代码实现

voidSelectSort(int*arr,intn){intbegin=0,end=n-1;while(begin<end){intmaxi=begin;intmini=begin;// 在 [begin, end] 中同时找最大值和最小值的下标for(inti=begin+1;i<=end;i++){if(arr[i]>arr[maxi]){maxi=i;}if(arr[i]<arr[mini]){mini=i;}}// 关键:如果 begin 位置恰好是最大值,第一次交换会把它移走// 需要让 maxi 指向最大值被移到的位置(即原来的 mini 位置)if(begin==maxi){maxi=mini;}swap(&arr[mini],&arr[begin]);// 最小值放到区间头swap(&arr[maxi],&arr[end]);// 最大值放到区间尾begin++;end--;}}

swap 顺序的陷阱:这是选择排序中最容易出错的细节。我们先交换minibegin,但如果begin恰好是maxi(即最大值就在区间头),第一次交换后最大值已经被移到了原来mini的位置,此时maxi仍然指向begin就会出错。所以需要先判断begin == maxi,将maxi更新为mini,确保第二次交换时maxi指向真正的最大值。

复杂度与稳定性

指标说明
最好时间复杂度O(n²) — 即使数组有序,仍然需要完整遍历
最坏时间复杂度O(n²)
平均时间复杂度O(n²)
空间复杂度O(1) — 原地排序
稳定性不稳定— 交换非相邻元素会打乱相等元素的相对顺序

选择排序是三种算法中唯一不稳定的排序。例如数组[5, 8, 5, 2],第一个 5 会和 2 交换,导致两个 5 的相对顺序发生改变。


三种排序对比

冒泡排序直接插入排序直接选择排序
最好时间O(n)O(n)O(n²)
最坏时间O(n²)O(n²)O(n²)
平均时间O(n²)O(n²)O(n²)
空间O(1)O(1)O(1)
稳定性稳定稳定不稳定
比较次数多(相邻比较)少(提前终止)多(必须扫完)
移动/交换次数多(每次比较可能交换)多(元素逐个后移)少(每轮最多2次交换)
适用场景小规模数据,教学入门基本有序的数据,小规模对交换次数敏感的场景

总结

  • 冒泡排序:思路最直观,适合入门理解排序的基本操作(比较和交换)。通过flag优化可以在有序时达到 O(n)。
  • 直接插入排序:模拟理牌过程,对于基本有序的数据表现极好(接近 O(n)),是小规模数据和部分排序场景的首选。
  • 直接选择排序:交换次数最少,但无论如何都要 O(n²) 的比较次数,且不稳定。双向优化可以减少遍历轮数,但不改变时间复杂度级别。

三种算法虽然在实际项目中很少直接使用(规模稍大就会被快排、归并等 O(n log n) 算法替代),但它们是理解更复杂排序算法的基石,也是面试中的高频考点。

http://www.jsqmd.com/news/955467/

相关文章:

  • 2026 年 6 月 5 日贵阳黄金铂金 K 金钻石五家回收门店实地测评 - 资讯速览
  • 2026年湖北孝感纸箱定做工厂实力对标:如何选择防水阻燃源头直供商 - 精选优质企业推荐官
  • 用数据科学做房产估值:可解释房价偏差的实战方法
  • AI写教材秘籍:借助低查重工具,快速完成教材创作
  • 终极图像分层神器:Layerdivider 一键将插画转换为可编辑PSD图层
  • Veo 2运动追踪失效的7个隐性诱因,第4个连官方文档都未标注(附实时波形诊断工具链)
  • 3步构建工业级PCB缺陷检测系统:DeepPCB数据集实战指南
  • 如何快速掌握SPT-AKI存档编辑:塔科夫离线版游戏进度管理终极指南
  • MATLAB递归批量处理框架:从文件遍历到并行加速的工程实践
  • PrismLauncher-Cracked:彻底解决Minecraft离线启动难题的终极指南
  • 百联OK卡回收最新指南 靠谱高价格平台解析 - 购物卡回收找京尔回收
  • STM32F746搭配USB3300实现10MB/s高速虚拟串口,CubeMX生成+IAR工程完整可运行
  • 房产估值偏差诊断:数据科学四步法实战指南
  • Navicat无限试用终极方案:macOS版14天限制一键解决完整指南
  • FPGA功耗分析与低功耗设计实战:从理论到优化策略
  • EBS: FND查询用户使用FORM情况
  • 3个步骤快速上手Bambu Studio:从零开始的3D打印切片完整教程
  • 2026年6月杭州集装箱定制行业研究报告:专业门店排行口碑榜 - GrowthUME
  • 卫生间漏水到楼下怎么查找漏水点?2026河池24小时上门维修电话TOP7机构推荐,免费勘察+精准定位,专业师傅处理屋顶墙体洗手间暗管漏水 - 一休咨询
  • DRAM技术演进:从工艺微缩到架构革新,应对物理极限与市场需求
  • 保姆级|Hermes Agent Windows 本地部署,环境配置 + 运行排坑全教程
  • Veo 2风格失控紧急响应协议:当生成结果偏离预期时,90秒内完成prompt重校准、latent重注入与refiner权重热切换
  • 从MobileNetV3的h-swish激活函数说起:PyTorch实战中如何为你的轻量级模型提速
  • 2026 西北旅游优质文旅企业甄选推荐|西北旅游哪家好靠谱旅行社盘点 - 深度智识库
  • AI教材写作秘籍:利用低查重AI工具,轻松打造优质教材!
  • 卫生间漏水到楼下怎么查找漏水点?2026贺州24小时上门维修电话TOP7机构推荐,免费勘察+精准定位,专业师傅处理屋顶墙体洗手间暗管漏水 - 一休咨询
  • Zotero双语引用样式CSL
  • ssl协商4 - 小镇
  • 2026年华南BOPP卷膜生产厂家盘点:规模化生产与高性价比之选 - 资讯速览
  • 2026年西安高顶商务车定制销售公司横向评测:奔驰威霆V300L高顶 丰田海狮改装 GL8 全国TOP3对比 - 深度智识库