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

排序算法——冒泡与快排

一、冒泡排序

1.1 定义

冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的序列,依次比较相邻的两个元素,如果它们的顺序错误(如升序时前一个大于后一个)就交换位置。每一轮遍历都会将当前未排序部分的最大(或最小)元素“冒泡”到序列的一端,因此得名“冒泡排序”。

1.2 实现流程

初始化:设定待排序序列长度为 nn,外层循环控制遍历轮数。

相邻比较:从第一个元素开始,依次比较相邻的两个元素。

条件交换:如果前一个元素大于后一个元素(升序排序),则交换它们的位置。

减少范围:每完成一轮遍历,最后一个元素即为当前最大值,下一轮遍历范围减少一位(即已排序部分不再参与比较)。

优化提前结束:设置一个标志位,若某一轮遍历中没有发生任何交换,说明序列已有序,可提前终止排序。

1.3 示例演示

以升序排序序列[5, 1, 4, 2, 8]为例:

轮次比较与交换过程结果
第1轮5>1交换→[1,5,4,2,8];5>4交换→[1,4,5,2,8];5>2交换→[1,4,2,5,8];5<8不交换[1,4,2,5,8]
第2轮1<4不交换;4>2交换→[1,2,4,5,8];4<5不交换[1,2,4,5,8]
第3轮无交换发生排序结束

1.5 代码实现

// 冒泡排序函数 void BubbleSort(SqList *L) { int i, j; int temp; // 外层循环控制排序的轮数 for (i = 0; i < L->length - 1; i++) { // 内层循环进行相邻元素的比较和交换 for (j = 0; j < L->length - 1 - i; j++) { if (L->r[j].key > L->r[j + 1].key) { // 交换相邻的元素 temp = L->r[j].key; L->r[j].key = L->r[j + 1].key; L->r[j + 1].key = temp; } } } } // 打印排序后的顺序表 void PrintList(SqList *L) { for (int i = 0; i < L->length; i++) { printf("%d ", L->r[i].key); } printf("\n"); } int main() { // 示例数据初始化 SqList L = {{5, 2, 9, 1, 5, 6}, 6}; // 排序前的顺序表 printf("Before sorting: "); PrintList(&L); // 调用冒泡排序 BubbleSort(&L); printf("After sorting: "); PrintList(&L); return 0; }

二、快速排序

2.1 定义

快速排序(Quick Sort)是一种基于分治思想的排序算法。它通过选择一个基准元素(枢轴),将待排序序列划分为两个子序列左侧子序列的所有元素都小于等于基准,右侧子序列的所有元素都大于等于基准,然后递归地对左右子序列进行同样的操作,最终使整个序列有序。

2.2 核心思想

  1. 分治策略:将大问题分解为若干小问题,分别解决后再合并。

  2. 原地排序:通过交换元素实现划分,不需要额外数组空间。

  3. 递归实现:对划分后的子数组重复执行相同操作,直到子数组长度为1或0。

2.3 实现流程

1. 选择枢轴

通常选择数组的第一个元素、最后一个元素或中间元素作为枢轴(pivot)

示例中假设选择arr[start]作为枢轴

2. 划分操作

设置两个指针ij,通常i从左侧开始,j从右侧开始

遍历数组,将小于枢轴的元素放到左侧,大于枢轴的元素放到右侧

最终将枢轴放置到正确位置,使得:

左侧所有元素 ≤ 枢轴

右侧所有元素 ≥ 枢轴

3. 递归排序

对枢轴左侧的子数组递归执行快速排序

对枢轴右侧的子数组递归执行快速排序

递归终止条件:子数组长度为 0 或 1(已有序)

2.4 示例演示

以升序排序数组[6, 1, 2, 7, 9, 3, 4, 5, 10, 8],选择第一个元素6为枢轴:

步骤操作结果
初始原数组[6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
划分小于6的放左边,大于6的放右边[1, 2, 3, 4, 5, 6, 7, 9, 10, 8]
递归左[1, 2, 3, 4, 5]排序[1, 2, 3, 4, 5]
递归右[7, 9, 10, 8]排序[7, 8, 9, 10]
合并最终有序数组[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

2.5 代码实现

// 分割函数:选择枢轴并进行分区操作 int partition(SqList *L, int low, int high) { int pivotkey; pivotkey = L->r[low].key; // 选择第一个元素作为枢轴 while (low < high) { // 从右边找到小于枢轴的元素 while (low < high && L->r[high].key >= pivotkey) { high--; } L->r[low] = L->r[high]; // 将小于枢轴的元素放到左边 // 从左边找到大于枢轴的元素 while (low < high && L->r[low].key <= pivotkey) { low++; } L->r[high] = L->r[low]; // 将大于枢轴的元素放到右边 } L->r[low].key = pivotkey; // 将枢轴元素放到正确的位置 return low; // 返回枢轴元素的位置 } // 快速排序函数 void quickSort(SqList *L, int low, int high) { if (low < high) { int pivotIndex = partition(L, low, high); // 获取枢轴位置 quickSort(L, low, pivotIndex - 1); // 对枢轴左边部分递归排序 quickSort(L, pivotIndex + 1, high); // 对枢轴右边部分递归排序 } }

2.6 复杂度比较

排序算法平均时间复杂度说明
快速排序O(nlog⁡n)O(nlogn)对于大多数随机分布的数据,效率非常高
冒泡排序O(n2)O(n2)效率较低,适合小规模数据
http://www.jsqmd.com/news/545638/

相关文章:

  • 光储充系统实战笔记:当光伏遇到充电桩的硬核玩法
  • 轻量OCR方案对比:OpenClaw+nanobot vs 商业API精度测试
  • 基于扩展卡尔曼滤波EKF的车辆状态估计探索
  • 别再让AI失忆了!手把手教你用Mem0为ChatGPT添加长期记忆(附Next.js实战代码)
  • UG模型转STP后总出问题?可能是STEP 203和214版本没选对
  • 解锁企业增长新引擎:揭秘湖南聚之唯如何用“小程序+AI”重塑行业竞争力
  • 2026管道电伴热,口碑好的伴热厂商推荐情况分析,电伴热供应商标朗科技专注产品质量 - 品牌推荐师
  • 博鳌亚洲论坛2026年年会—离岸投资:把握封关机遇,共创美好未来
  • UI 设计中的用户反馈机制:让交互更有温度
  • 从朱诺到威尼斯:一个可持续旅游模型如何‘开箱即用’解决你的美赛问题二
  • AI学习(张量复习)
  • 多模态扩展:OpenClaw+GLM-4.7-Flash处理图片信息
  • 上周刚把小区门口那家自助洗车店的自动控制系统调完,趁着记性还热乎,把这套用S7-200 PLC+MCGS组态屏的方案整理出来给大伙瞅瞅
  • Web地图开发避坑指南:墨卡托和UTM坐标系到底怎么选?
  • openclaw对接telegram渠道存在的问题
  • python扶贫助农系统及农副产品销售商城系统小程序的实现
  • 2026论文写作工具红黑榜:AI论文写作软件怎么选?用过才敢说!
  • 零基础学基于Linux的NPU固件开发​ 专栏7.3.3 下一步:尝试‘NPU固件+Linux驱动’联合开发
  • 别再为团队数据安全发愁了!手把手教你用Docker Compose在雨云服务器上部署Tailchat私有聊天室
  • 深入解析Android Activity生命周期与启动模式实战
  • LangChain4j + Qdrant 向量数据库实战:从 Docker 部署到 Spring Boot 集成
  • 5大维度重构Windows体验:开源系统优化方案全解析
  • 汽车ECU诊断工具选型与实践指南:开源方案的技术优势与应用策略
  • 数据库性能分析实战指南:构建高效监控与优化体系
  • OpenClaw+GLM-4.7-Flash智能搜索:个性化信息检索系统
  • VSCode + Git 实战:从单机开发到团队协作,你的第一个私有项目版本管理指南
  • 3步掌握智能媒体捕获:面向内容创作者的开源工具
  • 从投稿难到高效发刊:Paperxie AI 期刊论文写作,让学术发表少走 10 年弯路
  • AI代码审查实战:用机器学习揪出隐藏Bug
  • 基于深度学习的机动车再识别模型:从理论到实践