Appearance
15. 二维数组:矩阵与棋盘
一维数组像是一排连续的储物柜,只能处理“线”上的数据。 但如果是电影院的座位表、象棋的棋盘、或者是游戏里的迷宫地图,这种拥有“行”和“列”的二维平面数据,我们就必须祭出二维数组了。
1. 什么是二维数组?
你可以把二维数组想象成一张 Excel 表格,或者一个围棋棋盘。
cpp
// 语法:数据类型 数组名[行数][列数];
int map[3][4];这行代码向电脑申请了一个 3 行 4 列的表格,总共有 $3 \times 4 = 12$ 个格子。
2. 坐标法则:行优先
和一维数组一样,二维数组的“行号”和“列号”也是从 0 开始的! 我们用两个方括号来精确定位一个格子:数组名[行标][列标]。
| 第 0 列 | 第 1 列 | 第 2 列 | 第 3 列 | |
|---|---|---|---|---|
| 第 0 行 | map[0][0] | map[0][1] | map[0][2] | map[0][3] |
| 第 1 行 | map[1][0] | map[1][1] | map[1][2] | map[1][3] |
| 第 2 行 | map[2][0] | map[2][1] | map[2][2] | map[2][3] |
如果要给第 1 行、第 2 列的格子赋值为 99,代码就是:
cpp
map[1][2] = 99;3. 黄金搭档:嵌套循环遍历
处理二维数组时,必定会用到嵌套循环。外层循环控制走到了哪一“行”,内层循环控制这一行的每一“列”。
经典实战:批量读取一个 $3 \times 3$ 的矩阵,并原样打印输出。
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[3][3];
// 1. 嵌套循环输入
for (int i = 0; i < 3; i++) { // i 代表当前是第几行
for (int j = 0; j < 3; j++) { // j 代表当前是第几列
cin >> a[i][j];
}
}
// 2. 嵌套循环输出
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << a[i][j] << " ";
}
cout << endl; // 极易忘:每一行打印完后,必须要换行!
}
return 0;
}4. 💀 致命陷阱:行与列的数学直觉错乱
在数学坐标系中,我们习惯用 $(x, y)$ 来表示一个点,其中 $x$ 是横坐标(列),$y$ 是纵坐标(行)。 但在 C++ 的二维数组中,顺序是颠倒的! a[行][列] 相当于数学里的 $(y, x)$。 在做迷宫寻路、地图搜索的算法题时,千万不要把行和列写反,否则会直接越界导致 RE(运行错误)!
5. 动手实践
md
1. 打开左下角的代码沙盒。
2. 声明一个 3 行 3 列的二维数组,利用嵌套循环读入 9 个数字。
3. 挑战:求出这个矩阵的“主对角线”上元素的和(即左上角到右下角那条线,想想对角线上的元素的 `i` 和 `j` 有什么共同特征?)
*(提示:对角线上的元素,它的行号和列号是相等的,比如 a[0][0], a[1][1])*