插入排序循环边界应为 for (int i = 1; i < n; i++),内层 while (j >= 0 && arr[j] > key),起始索引为1,比较符升序用>,vector需用.size()而非sizeof。

插入排序的正确循环边界怎么写
很多人写 for 循环时从 i = 0 开始,结果越界或漏排——插入排序必须从第二个元素开始比较,因为第一个元素默认已“有序”。i 的起始值是 1,不是 0;终止条件用 i (<code>n 是数组长度),别写成 i ,语义不清还容易手抖多写个等号。
常见错误现象:std::out_of_range 或排序后末尾元素丢失。
- 内层
while循环判断顺序必须是j >= 0 && arr[j] > key,不能反过来——否则j减到 -1 后还访问arr[j],触发未定义行为 - 如果用
std::vector,记得用.size()获取长度,别硬写sizeof(arr)/sizeof(arr[0]),后者对 vector 无效 - 升序排列时,比较符用
>;降序就换,别只改循环不改条件
用 vector 还是原生数组?性能差多少
用 std::vector 更安全,但每次调 push_back 可能触发内存重分配;用原生数组(如 int arr[100])快一点,但长度固定、无法传参进函数(会退化为指针)。实际练习中优先用 vector,避免手动管理长度出错。
性能影响:小数据量(vector 的连续内存和缓存友好性反而可能略优,关键不在容器类型,而在是否用了 reserve() 预分配。
立即学习“C++免费学习笔记(深入)”;
- 若已知规模,构造时加
std::vector<int> arr; arr.reserve(n);</int> - 函数参数推荐写成
void insertion_sort(std::vector<int>& arr)</int>,引用传参避免拷贝 - 不要把数组名当指针传给需要
vector的函数——编译直接报错:no matching function
swap 操作写错导致逻辑错乱
插入排序本质是“腾位置”,不是交换相邻元素。典型错误是写成 std::swap(arr[j], arr[j+1]),这变成冒泡了。正确做法是把待插元素暂存为 key,然后把比它大的元素统一后移一位,最后把 key 填进空出来的位置。
容易踩的坑:后移时用 = 赋值,不是 += 或 ++;填 key 时下标是 j + 1,不是 j。
- 后移代码必须是
arr[j + 1] = arr[j];,不是arr[j] = arr[j + 1]; -
key一定要在内层循环前取,比如int key = arr[i];,不能在循环里反复读arr[i](i 可能变) - 别用
std::swap替代赋值——它交换两个值,破坏了“挪出空位”的前提
调试时怎么看中间状态没跑偏
插入排序每轮只保证前 i+1 个元素有序,所以打印中间结果时,重点看每次外层循环结束后,arr[0] 到 arr[i] 是否升序。随便打一行 cout 容易淹没关键信息,建议加标记:
for (int k = 0; k <= i; ++k) cout << arr[k] << " "; cout << " // sorted prefix up to index " << i << "\n";
常见错误现象:某轮输出里前面几个数乱序了,说明内层循环提前退出或边界错;或者某轮没输出,说明外层循环根本没跑——检查 i 初始化和 n 是否为 0 或负数。
- 测试用例至少覆盖三种情况:
{5,4,3,2,1}(全逆序)、{1,2,3,4,5}(已有序)、{3,1,4,1,5}(含重复) - 遇到
Segmentation fault,先检查j是否小于 0 后还在访问arr[j] - 如果排序后和输入一样,大概率是内层循环条件写反了,比如把
>写成
key 提取的位置——这两处一错,整个逻辑就静默失效,还不好 debug。











