CC++ & Algorithm

冒泡排序

中等0
语言版本:C++
概述:冒泡排序像水中的气泡一样,让较大的数慢慢“浮”到数组的末尾。

冒泡排序:让大数像泡泡一样浮到末尾

什么是冒泡排序?

想象一下你有一排小朋友按身高从矮到高排队,但是队伍现在乱糟糟的。你想把最高的同学移到最右边。冒泡排序就像吹泡泡一样——每次比较相邻两个小朋友,如果左边比右边高,就交换他们的位置。这样,最高的“气泡”就会慢慢“浮”到队伍的末尾。重复这个过程,直到所有小朋友都按身高排得整整齐齐。

冒泡排序是一种基于比较的排序算法,它通过不断“冒泡”把最大的元素送到末尾,整个过程就像水里的气泡上升一样。它特别简单,适合用来理解排序的基本思想,也适合数据量很少的时候使用。


原理分解:一步一步来

1. 核心步骤

  • 从数组的第一个元素开始,依次比较相邻的两个数
  • 如果左边的数比右边大,就交换它们(让大的往右走)。
  • 每一轮结束后,当前未排序部分中最大的数就会“浮”到最右边。
  • 重复上述步骤,但是每轮比较的范围缩小一个(因为末尾已经排好了)。
  • 如果某一轮没有发生任何交换,说明数组已经有序,可以提前结束。

2. 结合生活中的例子

假设我们有四个小朋友的分数(满分10分):score = [5, 3, 8, 1],我们按分数从小到大排。

第一轮:

  • 比较5和3 → 5>3,交换 → [3, 5, 8, 1]
  • 比较5和8 → 5<8,不交换 → [3, 5, 8, 1]
  • 比较8和1 → 8>1,交换 → [3, 5, 1, 8]
    第一轮结束,最大的8已经“浮”到了末尾。

第二轮:

  • 比较3和5 → 3<5,不交换 → [3, 5, 1, 8]
  • 比较5和1 → 5>1,交换 → [3, 1, 5, 8]
    第二轮结束,5来到了倒数第二的位置。

第三轮:

  • 比较3和1 → 3>1,交换 → [1, 3, 5, 8]
    第三轮结束,全部有序。

你看,就像泡泡一样,每次最大的数都慢慢漂到了右边。


新手最容易犯的错误

错误1:比较范围没有递减

很多同学会写成 for j in range(n-1),导致每一轮都从头比较到末尾,这样不仅浪费时间,而且已经排好的最大数又会被比较,甚至可能被交换回去。
正确做法:每轮比较次数 n-1-i,i是已经完成的轮数。

错误2:忘记用优化标记(swapped)

如果不加 swapped 标记,哪怕数组已经有序,程序仍然会傻傻地跑完所有轮次。虽然结果没错,但白白做了很多无用功。
正确做法:每轮开始时设 swapped=False,发生交换就设为 True;如果一轮结束 swapped 还是 False,直接 break

错误3:把 arr[j]arr[j+1] 比较方向弄反

如果想从小到大排序,当 arr[j] > arr[j+1] 时交换;如果想从大到小,就改成 arr[j] < arr[j+1] 时交换。


完整可运行的Python代码

下面是一段完整的代码,包含输入输出,并且每行变量都有中文注释:

def bubble_sort(arr):
    """对数组进行冒泡排序(从小到大)"""
    n = len(arr)                     # 数组长度
    for i in range(n - 1):           # 需要 n-1 轮
        swapped = False              # 标记这一轮是否发生过交换
        for j in range(n - 1 - i):   # 每轮比较次数递减
            if arr[j] > arr[j + 1]:  # 如果左边比右边大
                arr[j], arr[j + 1] = arr[j + 1], arr[j]  # 交换它们
                swapped = True       # 记录发生了交换
        if not swapped:              # 如果没有发生交换,说明已经排好
            break
    return arr

# ---------- 测试 ----------
# 让用户输入一串数字,用空格分隔
input_str = input("请输入一串整数,用空格分隔:")
nums = [int(x) for x in input_str.split()]  # 转换成整数列表

print("排序前:", nums)
bubble_sort(nums)
print("排序后:", nums)

运行示例

请输入一串整数,用空格分隔:5 3 8 1
排序前: [5, 3, 8, 1]
排序后: [1, 3, 5, 8]

你也可以在代码里直接测试:

# 也可以用现成的列表测试
scores = [5, 3, 8, 1]
bubble_sort(scores)
print(scores)  # 输出 [1, 3, 5, 8]

小贴士:何时用冒泡排序?

  • 数据非常少(比如10个以内):冒泡排序代码简洁,容易写对。
  • 数据基本有序:用了 swapped 优化后,几乎只要一轮就完成,速度很快(接近 O(n))。
  • 你只是想理解排序原理:冒泡排序是最直观的入门算法。
  • 不推荐:数据量很大(比如几千个)时,冒泡排序非常慢(最坏 O(n²))。这时候应该用更快的算法,比如快速排序、归并排序等。

相关指引:还想学更多排序?

冒泡排序是排序算法家族的入门成员。如果你掌握了它,可以继续学习:

  • [选择排序]:每次从剩余元素中挑出最小的,放到最前面。
  • [插入排序]:像整理扑克牌一样,把新牌插入到已排序的手牌中。
  • [计数排序]:如果数据是范围不大的整数,数一数每个数出现几次就能排好,超快。
  • [排序算法比较]:了解每种算法的优缺点,学会根据数据特点选择合适的工具。

你可以在本站搜索对应的标识符来找到它们:
cspj-selection-sort-py(选择排序)
cspj-insertion-sort-py(插入排序)
cspj-counting-sort-py(计数排序)
cspj-sort-comparison-py(排序算法对比)


现在你已经学会了冒泡排序,快试试自己写一个吧!记得从最简单的例子开始,比如帮你自己的零花钱清单排序,或者帮班级成绩单排序。编程就是这样,从一个小气泡开始,慢慢变成大本领。

例题精讲

1单选题

关于冒泡排序的基本思想,下列描述正确的是?

A每次将当前最大元素放到数组开头
B每次比较相邻的两个元素,将较大的元素交换到后面
C每次选取一个基准值进行划分,将小于基准值的放在左边,大于的放在右边
D每次将当前最小元素放到数组末尾
2判断题

在冒泡排序中,如果某一趟排序过程中没有发生任何元素交换,则可以判定数组已经有序,并可以提前结束排序。

3填空题
以下是一个冒泡排序的Python函数,请补全内层循环的终止条件。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n-1):
        for j in range(___):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr
4单选题

冒泡排序在最坏情况下的时间复杂度是?

AO(n)
BO(n log n)
CO(n²)
DO(1)
5判断题

冒泡排序是一种稳定的排序算法。