中职对口高考 · 算法专题

冒泡排序算法

最经典的排序算法,通过相邻元素两两比较,让大数逐步后移、小数逐步前移,如同水中气泡上浮。

📚 必考核心算法 ⏱ 约15分钟 💻 VS2010 / C#

1算法原理

冒泡排序(Bubble Sort)是中职阶段最常用、考查频率最高的排序算法。因其排序过程如同水中气泡上浮,大数逐步向后漂浮、小数逐步向前漂浮,故而得名冒泡排序。

💡 核心原理

对无序数组进行多轮遍历,每一轮都相邻两个元素两两对比,如果两个元素不满足排序规则(升序:前大后小需交换;降序:前小后大需交换),就交换两个元素的位置。

排序规则(升序)

相邻元素中,前一个数 > 后一个数 → 交换位置。每一轮排序结束后,当前未排序区间的最大值会"沉"到末尾。

循环逻辑拆解(必考理解点)

🔄 外层 for 循环

作用:控制排序总轮次

n 个元素的数组,最多需要 n-1 轮排序。因为每一轮至少确定一个元素的最终位置,n-1 轮后剩下的那个元素自然有序。

🔁 内层 for 循环

作用:控制每一轮的相邻对比次数

每完成一轮,末尾已有序元素增加一个,因此对比次数逐轮减少。第 i 轮对比次数为 n-1-i。

🔑 两个核心节点:比较 & 交换

冒泡排序的核心操作只有两个——比较和交换。下面通过动态图结合代码,直观理解这两个关键节点:

🔍 比较节点
🔄 交换节点
点击上方按钮,查看比较和交换两个核心节点的动态演示
📄 C# 代码 - 比较节点
💡
记忆口诀:外层 n 减 1,内层 n 减 1 再减 i。升序大于才交换,一轮一个最大去最后。
理解:外层循环跑 n-1 轮,内层每轮少比一次(因为末尾越来越多元素已就位)。

2动画演示

下面通过完整的动画演示,一步步展示数组 int[] arr = { 9, 5, 1, 4, 3 } 的冒泡排序全过程。左侧是数组动画,右侧是同步高亮的 C# 代码,帮助你将算法逻辑与代码行一一对应。

🎬 冒泡排序完整演示
速度:
讲解 状态: 就绪
点击"播放讲解"开始观看动画演示,语音会同步讲解每一步的操作和对应的代码含义。
-
当前轮次
-
本轮对比
0
交换次数
0
已归位元素
📝 C# 代码(同步高亮)
步骤 0 / 0 进度

🎨 颜色图例

未排序元素
正在比较
正在交换
已排序归位

3算法流程图

流程图是理解算法逻辑的重要工具。下面是冒泡排序(升序)的完整流程图,帮助你梳理从开始到结束的每一步判断和操作:

冒泡排序
图1:冒泡排序算法流程图(升序标准版)
✅ 读图要点

看流程图要抓住三个关键:外层循环条件(轮次)、内层循环条件(每轮对比次数)、判断交换条件(升序用 >,降序用 <)。这三个点也是高考选择题和程序填空题的高频考点。

4在线调试工具

本工具支持 C# 代码的在线编辑、运行和调试。你可以直接修改代码,点击"运行"按钮查看输出结果。如果代码有错误,系统会自动检测并提示错误信息,帮助你定位问题。

⚡ C# 在线编译器 (冒泡排序教学专用)
📤 运行结果
// 点击"运行"按钮执行代码,结果将显示在这里

📝 练习题

下面提供两道练习题,请结合上面的在线调试工具完成。做完后可以运行代码验证答案是否正确。

1
程序改错题 中等
下面这段冒泡排序代码中有 3 处错误,请找出并修正,使程序能正确输出升序排列结果。
提示:错误分别出现在循环条件、判断条件和变量使用上。
C# - 有错误的代码 共 3 处错误
1using System;
2class Program
3{
4    static void Main()
5    {
6        int[] arr = { 9, 5, 1, 4, 3 };
7        int len = arr.Length;
8
9        // 错误1:外层循环条件错误
10        for (int i = 0; i < len; i++)  // 错!
11        {
12            // 错误2:内层循环条件错误
13            for (int j = 0; j < len - i; j++)  // 错!
14            {
15                // 错误3:判断条件方向反了
16                if (arr[j] < arr[j + 1])  // 错!
17                {
18                    int temp = arr[j];
19                    arr[j] = arr[j + 1];
20                    arr[j + 1] = temp;
21                }
22            }
23        }
24
25        Console.WriteLine("排序结果:");
26        foreach (int item in arr)
27            Console.Write(item + " ");
28    }
29}
提示:
① 外层循环:n个元素只需要n-1轮,想想为什么?
② 内层循环:每轮要和下一个元素比较,j+1不能越界,而且要跳过已排好序的元素。
③ 判断条件:升序排列,应该是前数大于后数才交换,这样大的数才能往后"冒泡"。
2
程序填空题 简单
请补全下面的冒泡排序代码(共 4 个空),使程序实现降序排序(从大到小)。
C# - 填空练习(降序) 共 4 个空
1using System;
2class Program
3{
4    static void Main()
5    {
6        int[] arr = { 9, 5, 1, 4, 3 };
7        int len = arr.Length;
8        int temp;
9
10        for (int i = 0; i < 空1; i++)
11        {
12            for (int j = 0; j < 空2; j++)
13            {
14                if (arr[j] 空3 arr[j + 1]) // 降序判断
15                {
16                    temp = 空4;
17                    arr[j] = arr[j + 1];
18                    arr[j + 1] = temp;
19                }
20            }
21        }
22
23        Console.WriteLine("降序排序结果:");
24        foreach (int item in arr)
25            Console.Write(item + " ");
26    }
27}
提示:
空1:外层循环轮次,n个元素需要几轮?参考升序版本。
空2:内层循环条件,每轮比较到哪里为止?
空3:降序的判断条件——前数和后数是什么关系时才交换?(升序用 > ,那降序呢?)
空4:交换的第一步,用temp临时保存哪个变量的值?

5算法特点与考点

👍 优点

  • 逻辑简单、代码结构固定
  • 易于理解和手写代码
  • 适配所有基础排序考题
  • 空间复杂度低,原地排序

👎 缺点

  • 嵌套循环,时间复杂度高
  • 数据量大时效率很低
  • 普通版本无法提前结束
  • 交换次数多(逆序时)

🎯 核心考点

  • 相邻元素对比:冒泡排序最核心的操作就是相邻两个元素比较,这是它与其他排序算法最直观的区别。
  • n-1 轮排序:外层循环执行 n-1 轮。选择题常考"数组长度为n,冒泡排序需要几轮?"
  • 逐轮缩减对比范围:内层循环条件为 j < len-1-i,每轮少比一次。
  • 升序降序切换:只需修改 if 判断条件——升序用 >,降序用 <。

📊 算法复杂度(对口高考新增必考考点)

复杂度类型 情况分类 结果 详细说明
时间复杂度 最差情况(完全逆序) O(n²) 每一轮都需要全部对比 + 大量交换操作
最优情况(已有序) O(n²) 普通冒泡无有序优化,依然完整执行双层循环
平均情况 O(n²) 中职考题统一记忆标准,都是平方级
空间复杂度 所有情况 O(1) 仅使用 1 个临时交换变量 temp,属于原地排序,不占用额外数组空间
稳定性 稳定排序 — 相等元素不会交换位置,相对顺序保持不变
⚠️ 注意

很多同学会误以为"数组已经有序时冒泡排序只需要O(n)"——不对!那是经过"标记优化"的冒泡排序。普通标准版冒泡排序无论数组是否有序,都会完整执行 n-1 轮,因此最优时间复杂度仍然是 O(n²)。考试时题目说"冒泡排序"默认指标准版,不考虑优化版本。

6易错点与核心逻辑

❌ 常见易错点

  • 1
    外层循环写成 i < len 正确写法是 i < len - 1。n 个元素只需要 n-1 轮。如果写 len,会多循环一轮,虽然结果可能没错(因为内层循环会变成 0 次),但概念上是错误的,考试会扣分。
  • 2
    内层循环写成 j < len - i 正确写法是 j < len - 1 - i。因为每次比较的是 j 和 j+1,如果 j 到 len-1,j+1 就越界了!末尾少写一个 -1 会导致"索引超出数组界限"的运行时错误。
  • 3
    升序降序搞反 升序用 arr[j] > arr[j+1](大的往后走),降序用 arr[j] < arr[j+1](小的往后走)。记忆技巧:想让哪边的数"冒"到末尾,就用相反的符号——升序让大数冒到末尾,所以用大于号。
  • 4
    交换时变量赋值顺序错误 正确顺序:temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp;。常见错误是把第一步写成 arr[j] = arr[j+1],这样 arr[j] 的原始值就丢失了,交换就失败了。一定要先用 temp 保存!
  • 5
    忘记声明 temp 变量 temp 必须在使用前声明。可以在循环外面声明一次(推荐),也可以在 if 里面声明(每次都新建,不推荐但也能跑)。但如果既没声明又直接用,编译器会报错"当前上下文中不存在名称 temp"。
  • 6
    混淆数组下标从 0 开始 C# 数组下标从 0 开始,arr[0] 是第一个元素,arr[len-1] 是最后一个。循环条件中所有的 -1 都是因为这个原因。记忆:长度为 n 的数组,下标范围是 0 到 n-1。
  • 7
    认为冒泡排序最优是 O(n) 普通冒泡排序的最优时间复杂度仍然是 O(n²),因为没有提前终止机制。只有加了 flag 标记位的"优化冒泡排序"才能做到有序时 O(n)。考试按标准版记忆 O(n²)。

🧠 核心逻辑总结

📐 公式记忆法

外层:for(i=0; i<n-1; i++) —— 轮次 = 元素数 - 1
内层:for(j=0; j<n-1-i; j++) —— 每轮对比数 = 总数 - 1 - 已排好的轮次
判断:if(arr[j] > arr[j+1]) —— 升序大于才交换(降序小于才交换)

🛠 三步写出冒泡排序

  1. 写外层循环:for (int i = 0; i < len - 1; i++) — 控制轮次
  2. 写内层循环:for (int j = 0; j < len - 1 - i; j++) — 控制每轮对比
  3. 写 if 判断 + 交换:升序用 >,降序用 <,交换用三行 temp 模板
🎯
一句话总结:冒泡排序就是"两两相比,大的往后走,一轮一个最大值"。抓住这三句话,整个算法的骨架就清楚了。再配上"外层 n-1,内层 n-1-i"的公式,写代码就不会错。