C++ · 控制结构
循环嵌套(多层循环)
用乘法表和计数例子理解嵌套循环,区分内外层执行次数,并用括号明确嵌套 if 中 else 的归属。
内外层循环与分支嵌套
想象一个班有 3 行同学,每行 4 人,要逐个点名——先点第 1 行第 1 个、第 1 行第 2 个……第 1 行点完再点第 2 行……这就是双重循环的场景。
外层循环控制"行",内层循环控制"列",每次外层循环执行 1 次,内层循环就执行一整圈。
执行次数:外层循环 m 次 × 内层循环 n 次 = 共执行 m×n 次。
break 只跳出最近一层循环,不能一次跳出所有层。
嵌套 if 同理:if 里面还有 if,用缩进让层次清晰,用大括号明确范围。
分支嵌套:在一个分支中继续判断另一个条件,适合“先确定大类,再细分”的规则。每层条件只在执行到该层时判断。用大括号明确每个 else 的归属,不能依赖缩进改变 C++ 语义。
嵌套循环:逐步追踪 i、j 和输出
每次进入外层循环体,内层的 j 都重新从 1 开始。先预测下面程序打印几行,再按顺序核对。
#include <iostream>
int main() {
for (int i = 1; i <= 2; ++i) {
for (int j = 1; j <= 3; ++j) {
std::cout << i << " " << j << "\n";
}
}
}| 打印顺序 | i | j | 该行输出 |
|---|---|---|---|
| 1 | 1 | 1 | 1 1 |
| 2 | 1 | 2 | 1 2 |
| 3 | 1 | 3 | 1 3 |
| 4 | 2 | 1 | 2 1 |
| 5 | 2 | 2 | 2 2 |
| 6 | 2 | 3 | 2 3 |
j 增到 4 后内层结束;i 增到 2 时,新的内层 j 又从 1 开始。最后 i 增到 3,外层结束,不会打印 i=3 或 j=4。
先自己判断:把 i 的上限改成 3,共打印几行?第 7 行是什么?
共 3×3=9 行;第 7 行是 3 1,因为新的内层循环重新初始化 j。
嵌套循环时间复杂度:矩形与三角形
在每次循环体工作量固定、没有提前退出时,外层 n 次、内层每次 m 次,总次数是 n×m,时间复杂度 O(nm)。若 m 固定为 3,随 n 增长是 O(n);两层循环不一定就是 O(n²)。
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
// 每次执行固定工作量
}
}这里内层分别执行 1、2、…、n 次,总计 n(n+1)/2,n≥1 时为 Θ(n²)。n=3 时是 1+2+3=6 次,不是 3×3=9 次。这些仅用固定数量计数变量的例子辅助空间 O(1),不计输出存储。
break 退出包含它的最近一层循环。放在内层的 continue 跳过本次内层剩余语句,然后执行内层 for 的更新;它不会跳过外层余下的语句。若把 if (j == 2) break; 放在第一个例子的输出语句之前,每行只打印 j=1,输出 1 1、2 1;换成 continue,则输出 1 1、1 3、2 1、2 3。
先自己判断:内层只跑到固定的 5,外层跑 n 次,时间复杂度是多少?
循环体执行 5n 次,在每次工作量固定时是 O(n),不是 O(n²)。
执行次数与 else 归属示例
例1:打印乘法口诀表
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
cout << j << "*" << i << "=" << i*j << " ";
}
cout << endl;
}
return 0;
}外层 i 从 1 到 9 控制行,内层 j 从 1 到 i 控制列,共执行 1+2+...+9=45 次乘法,输出标准的九九乘法表。
例2:双重循环统计总次数
#include <iostream>
using namespace std;
int main() {
int cnt = 0;
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 4; j++) {
cnt++;
}
}
cout << cnt << endl; // 输出 12
return 0;
}外层 3 次 × 内层 4 次 = 共执行 12 次,输出 12。这是计算嵌套循环执行次数的基本方法。
例3:先判断是否及格,再判断是否优秀
#include <iostream>
using namespace std;
int main() {
int score = 85;
if (score >= 60) {
if (score >= 90) cout << "excellent" << endl;
else cout << "pass" << endl;
} else {
cout << "retry" << endl;
}
}输出 pass。外层决定是否及格,进入后内层再判断是否优秀;外层 else 只处理不及格。
例4:用括号明确 else 属于哪层
#include <iostream>
using namespace std;
int main() {
bool registered = false, paid = true;
if (registered) {
if (paid) cout << "ready" << endl;
} else {
cout << "register first" << endl;
}
}输出 register first。else 与外层 if 对应;如果去掉外层大括号,它可能改与内层 if 匹配,未报名时反而不输出提示。
提示
- 内层次数固定时可用外层次数相乘;若内层上限随外层改变,需逐轮相加,例如 1+2+…+n。
- break 只退出当前层循环,要退出多层需要设置标志变量或用 goto(竞赛慎用)。
- 嵌套层次越深,代码越难读;超过三层时考虑能否用数组或函数简化。
- 内外层循环变量名要用不同字母(常用 i、j、k),不要重名。
- 调试嵌套循环时,先在脑海里"手动模拟"几步,追踪 i、j 的变化是最可靠的方法。
先修知识
技术参考
范围说明
本站讲解由 InfoCode 编写,不是官方考纲;参考级别是本站映射,不代表官方等级、认证或参赛资格。练习记录不等于掌握或资格。
参考级别:GESP 2 级(本站映射)