多层循环语句 (Nested Loops)
1. 概念介绍
多层循环(或嵌套循环)是指在一个循环语句的循环体内,又包含另一个完整的循环语句。最常见的是两层循环,我们称之为外层循环和内层循环。其执行的特点是:外层循环每执行一次,内层循环都要完整地执行一遍。
2. 算法步骤
- 外层循环开始。
- 外层循环的第一次迭代开始。
- 内层循环开始。
- 内层循环执行其所有迭代,直到其条件为假。
- 内层循环结束。
- 外层循环第一次迭代的剩余部分(如果有的话)执行完毕。
- 外层循环进行下一次迭代的判断。如果条件为真,返回第2步;如果为假,整个多层循环结束。
总执行次数 = 外层循环次数 × 内层循环次数。
3. 算法可视化SVG图示
4. 核心特性
- 乘法效应: 总迭代次数是各层循环迭代次数的乘积,这导致时间复杂度迅速增加。两层循环通常是 O(n²),三层是 O(n³)。
- 维度扩展: 多层循环很自然地对应多维数据结构,如用两层循环处理二维数组(矩阵)。
- 内外关系: 内层循环可以使用外层循环的控制变量,这使得生成依赖于外层状态的复杂模式(如打印三角形)成为可能。
5. C++代码基础实现
#include <iostream>
int main() {
// 任务:打印一个 5x5 的星号矩阵
const int SIZE = 5;
// 外层循环控制行 (i)
for (int i = 0; i < SIZE; ++i) {
// 内层循环控制列 (j)
for (int j = 0; j < SIZE; ++j) {
std::cout << "* ";
}
// 每打印完一行后,换行
std::cout << std::endl;
}
return 0;
}
输出:
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
6. 优化策略
- 减少内层循环的计算: 内层循环是执行最频繁的地方,应尽可能简化其代码。
- 循环交换 (Loop Interchange): 在处理二维数组时,交换内外层循环的顺序有时可以改善缓存命中率,从而提高性能(通常让内层循环遍历连续的内存地址)。
- 提前退出: 如果在内层循环中找到了需要的结果,应使用
break(可能需要配合标志位flag来跳出外层循环)或goto提前终止所有循环,避免不必要的计算。
7. 优缺点
- 优点:
-
- 能够处理多维数据和复杂的组合问题。
- 是许多基础算法(如排序、搜索)的自然实现方式。
- 缺点:
-
- 高时间复杂度,是性能瓶颈的主要来源。在竞赛中,O(n²) 的算法通常只能处理 n≈10³-10⁴ 的数据,O(n³) 只能处理 n≈10²-10³ 的数据。
- 逻辑可能变得复杂,难以理解和调试。
8. 应用场景
- 二维数组/矩阵操作: 遍历、初始化、矩阵乘法等。
- 组合枚举: 找出所有可能的配对,如 "百钱百鸡" 问题,或在数组中找出所有和为定值的数对。
- 排序算法: 冒泡排序、选择排序、插入排序都使用两层循环。
- 打印图形和模式: 打印各种三角形、菱形、正方形等。
9. 扩展
-
不规则嵌套循环: 内层循环的边界可以依赖于外层循环的变量。
// 打印一个直角三角形 for (int i = 1; i <= 5; ++i) { // 外层控制行 for (int j = 1; j <= i; ++j) { // 内层循环次数由i决定 std::cout << "* "; } std::cout << std::endl; } -
跳出多层循环:
bool found = false; for (int i = 0; i < N && !found; ++i) { for (int j = 0; j < M; ++j) { if (condition) { found = true; break; // 跳出内层 } } }
10. 课后配套练习
- 九九乘法表: 打印标准的九九乘法表。
- 打印倒直角三角形: 输入一个整数N,打印一个N行的倒直角星号三角形。
- 寻找素数: 输入一个整数N,输出2到N之间所有的素数。(提示:外层循环遍历2到N,内层循环判断当前数是否为素数)。
- 找出数组中的数对: 给定一个整数数组和一个目标值
target,找出数组中是否存在两个数的和等于target。 - 打印空心菱形: 输入一个奇数N,打印一个高度为N的空心菱形。
点击查看答案
1. 九九乘法表
#include <iostream>
#include <iomanip>
int main() {
for (int i = 1; i <= 9; ++i) {
for (int j = 1; j <= i; ++j) {
std::cout << j << "*" << i << "=" << std::setw(2) << i * j << " ";
}
std::cout << std::endl;
}
return 0;
}
2. 打印倒直角三角形
#include <iostream>
int main() {
int n;
std::cin >> n;
for (int i = n; i >= 1; --i) {
for (int j = 1; j <= i; ++j) {
std::cout << "* ";
}
std::cout << std::endl;
}
return 0;
}
3. 寻找素数
#include <iostream>
#include <cmath>
int main() {
int n;
std::cin >> n;
for (int i = 2; i <= n; ++i) {
bool is_prime = true;
for (int j = 2; j * j <= i; ++j) {
if (i % j == 0) {
is_prime = false;
break;
}
}
if (is_prime) {
std::cout << i << " ";
}
}
std::cout << std::endl;
return 0;
}
4. 找出数组中的数对
#include <iostream>
#include <vector>
int main() {
int arr[] = {2, 7, 11, 15};
int target = 9;
int n = sizeof(arr) / sizeof(arr[0]);
bool found = false;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (arr[i] + arr[j] == target) {
std::cout << "找到了: " << arr[i] << " 和 " << arr[j] << std::endl;
found = true;
break;
}
}
if (found) break;
}
return 0;
}
5. 打印空心菱形
#include <iostream>
#include <cmath>
int main() {
int n;
std::cin >> n;
int mid = n / 2;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (abs(i - mid) + abs(j - mid) == mid) {
std::cout << "*";
} else {
std::cout << " ";
}
}
std::cout << std::endl;
}
return 0;
}
11. 相关网络资源推荐
- OI Wiki - 循环结构 (包含嵌套循环示例)
- GeeksforGeeks - Nesting of loops in C++
- VisuAlgo.net - 许多算法(如排序)的可视化,能帮助理解嵌套循环的执行过程。