冒泡排序需两层for循环:外层i遍历len(arr)-1轮,内层j遍历len(arr)-1-i次,用arr[j]与arr[j+1]比较交换;加swapped标志可提前终止;其时间复杂度为o(n²),远低于python内置sorted()的o(n log n)。

冒泡排序基础写法:两层 for 循环怎么套才不越界
下标从 0 开始,外层控制轮数,内层负责相邻比较——但内层上限容易写错。常见错误是把 range(len(arr)) 直接套进内层,导致最后一步访问 arr[i+1] 越界。
- 外层循环轮数最多
len(arr) - 1次(排完 n-1 轮,最后一个自然就位) - 内层每次可缩小范围:第 i 轮后,末尾 i 个元素已有序,所以内层用
range(len(arr) - 1 - i) - 比较时统一用
j和j + 1下标,确保不越界
for i in range(len(arr) - 1):
for j in range(len(arr) - 1 - i):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
提前结束优化:什么时候该设 swapped 标志位
如果某一轮遍历中一次交换都没发生,说明数组已经有序,后续轮次纯属浪费。这时候靠布尔标志位跳出外层循环,不是锦上添花,而是对近乎有序数据的刚需。
- 每轮开始前设
swapped = False - 只要发生一次交换,就置为
True - 本轮结束后检查,若仍是
False,直接break - 别在内层一交换就
break外层——那会漏掉本轮其他比较
for i in range(len(arr) - 1):
swapped = False
for j in range(len(arr) - 1 - i):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
if not swapped:
break
sorted() 和手写冒泡的区别:别拿它当性能方案用
Python 的 sorted() 是 Timsort,平均 O(n log n),而冒泡稳定在 O(n²)。即使加了 swapped 优化,最坏情况(逆序)还是得跑满 n-1 轮,每轮比较数递减但总量仍是 ~n²/2。
- 手写冒泡只适合教学、调试理解排序逻辑,或极小数据(
- 真实业务里用
sorted(arr)或arr.sort(),别自己造 O(n²) 的轮子 - 想观察过程?加
print(arr)在每轮结束后,比改算法更实际
边界情况容易漏:空列表、单元素、重复值怎么走
空列表和单元素列表进两层循环会直接跳过内层(range(0)),没问题;但重复值不影响逻辑,冒泡本来就是稳定排序。真正容易出问题的是输入非列表类型,比如传了字符串或元组——它们不可变,arr[j], arr[j + 1] = ... 会报 TypeError。
- 函数开头加一句
if not isinstance(arr, list): raise TypeError("expected list") - 不建议自动转
list(arr),因为字符串转列表会拆成字符,语义已变 - 原地排序(
arr.sort())和返回新列表(sorted())是两种契约,手写冒泡默认是原地,别悄悄返回新列表让人困惑
冒泡排序的“提前结束”不是可选项,是面对真实数据时避免无意义计算的必要判断;但它的价值从来不在性能,而在你能一眼看清每轮发生了什么——这点在调试排序逻辑或教新人时,比快慢更重要。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











