冒泡排序正确循环边界应为外层i从0到n-1、内层j从0到n-i-1;需传引用避免副本修改;交换时用引用确保原容器有序。

冒泡排序的正确循环边界怎么写
很多人写 bubble_sort 时内层循环用 i 或 <code>j ,结果越界或少跑一趟。核心是:每轮把最大元素“冒”到末尾,所以第 <code>i 轮(从 0 开始)后,末尾 i 个位置已有序,内层只需比较到 n - 1 - i。
- 外层
i从0到n - 1(共n轮,但最后一轮其实只比一次,可优化) - 内层
j从0到n - 2 - i(保证arr[j+1]不越界) - 若某轮没发生交换,可提前退出——这是实际项目里必须加的优化
std::vector 和 int[] 的实现差异
用 std::vector 时容易忘记调用 .size(),直接写 arr.length() 会编译失败;而原生数组传参后退化为指针,sizeof(arr)/sizeof(*arr) 在函数内部失效。
-
std::vector版本必须传引用:void bubble_sort(std::vector<int>& arr)</int>,否则拷贝开销大 - 原生数组推荐封装成模板:
template<size_t n> void bubble_sort(int (&arr)[N])</size_t>,这样N可推导 - 混用
std::array更安全:std::array<int> a = {3,1,4,1,5}; bubble_sort(a);</int>,它保留长度且不退化
为什么 swap 用 std::swap 而不是手写临时变量
手写 int t = a; a = b; b = t; 看似简单,但遇到自定义类型(比如含资源管理的类)会出问题:可能调用默认拷贝构造,引发浅拷贝、重复释放等 undefined behavior。
-
std::swap是特化的,对std::vector、std::string等做指针交换,O(1) 且安全 - C++11 后支持移动语义,
std::swap自动利用std::move,避免深拷贝 - 即使对
int,现代编译器也能优化掉std::swap的函数调用,和手写一样快
调试时最常见的三个错误现象
跑起来结果不对,大概率不是算法逻辑错,而是这些低级但难察觉的问题。
立即学习“C++免费学习笔记(深入)”;
- 内层循环写成
j (应为 <code>j ),导致访问 <code>arr[n - i]越界,触发std::out_of_range或静默内存破坏 - 比较用
>=而不是>,稳定排序变不稳定(相同值相对顺序改变),在需要稳定性的场景下很难定位 - 忘记加
&传引用,函数里排序的是副本,原容器完全没变,打印出来还是乱序
冒泡排序本身很简单,但边界、传参、交换这三个点,每个都卡过至少一半人。写完别急着测数据,先盯住这三处。











