信奥崔老师:多层循环语句 (Nested Loops)

60 阅读5分钟

多层循环语句 (Nested Loops)

1. 概念介绍

图片

多层循环(或嵌套循环)是指在一个循环语句的循环体内,又包含另一个完整的循环语句。最常见的是两层循环,我们称之为外层循环和内层循环。其执行的特点是:外层循环每执行一次,内层循环都要完整地执行一遍

2. 算法步骤

  1. 外层循环开始。
  2. 外层循环的第一次迭代开始。
  3. 内层循环开始。
  4. 内层循环执行其所有迭代,直到其条件为假。
  5. 内层循环结束。
  6. 外层循环第一次迭代的剩余部分(如果有的话)执行完毕。
  7. 外层循环进行下一次迭代的判断。如果条件为真,返回第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 foundfalse;
    for (int i0; i < N && !found; ++i) {
        for (int j0; j < M; ++j) {
            if (condition) {
                foundtrue;
                break; // 跳出内层
            }
        }
    }
    

10. 课后配套练习

  1. 九九乘法表:  打印标准的九九乘法表。
  2. 打印倒直角三角形:  输入一个整数N,打印一个N行的倒直角星号三角形。
  3. 寻找素数:  输入一个整数N,输出2到N之间所有的素数。(提示:外层循环遍历2到N,内层循环判断当前数是否为素数)。
  4. 找出数组中的数对:  给定一个整数数组和一个目标值 target,找出数组中是否存在两个数的和等于 target
  5. 打印空心菱形:  输入一个奇数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 target9;
      int n = sizeof(arr) / sizeof(arr[0]);
      bool foundfalse;
      for (int i0; 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;
                  foundtrue;
                  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 - 许多算法(如排序)的可视化,能帮助理解嵌套循环的执行过程。