二维数组像一张表格,有行和列两个维度,适合存储矩阵、棋盘、地图等具有"行列结构"的数据。
6.2
二维数组像一张表格,有行和列两个维度,适合存储矩阵、棋盘等数据。语法是 类型 数组名[行数][列数];。
matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], ... 依次排开。"行列"只是我们理解数据的方式,底层存储和一维数组一样是连续的。| 1 | int matrix[2][3] = |
| 2 | { |
| 3 | {1, 2, 3}, // 第0行 |
| 4 | {4, 5, 6} // 第1行 |
| 5 | }; |
| 6 | |
| 7 | cout << matrix[0][1]; // 输出:2 |
| 8 | cout << matrix[1][2]; // 输出:6 |
| 9 | |
| 10 | // 嵌套循环遍历(见 5.3 节) |
| 11 | for (int i = 0; i < 2; i++) // 遍历行 |
| 12 | { |
| 13 | for (int j = 0; j < 3; j++) // 遍历列 |
| 14 | cout << matrix[i][j] << " "; |
| 15 | cout << endl; |
| 16 | } |
二维数组的初始化和一维数组类似,但有一条容易被忽视的规则:第一维(行数)可以省略,第二维(列数)不能省略。
| 1 | // 完整初始化 |
| 2 | int a[2][3] = {{1,2,3},{4,5,6}}; |
| 3 | |
| 4 | // 省略第一维(行数),编译器会自动数一共有几行 |
| 5 | int b[][3] = {{1,2,3},{4,5,6}}; // 自动推断为 2 行 |
| 6 | |
| 7 | int c[2][] = {{1,2,3},{4,5,6}}; // ❌ 错误!列数不能省略 |
| 8 | |
| 9 | // 部分初始化,缺省的位置自动补 0 |
| 10 | int d[2][3] = {{1,2}}; // → {{1,2,0},{0,0,0}} |
matrix[i][j] 对应的内存位置,所以列数是不可或缺的。二维数组最常见的两个基础操作:把所有元素累加求和,以及把矩阵"转置"(行列互换,matrix[i][j] 变成 matrix[j][i])。
| 1 | int a[2][3] = {{1,2,3},{4,5,6}}; |
| 2 | |
| 3 | // ── 求所有元素之和 ── |
| 4 | int sum = 0; |
| 5 | for (int i = 0; i < 2; i++) |
| 6 | for (int j = 0; j < 3; j++) |
| 7 | sum += a[i][j]; // 21 |
| 8 | |
| 9 | // ── 矩阵转置:行列互换 ── |
| 10 | int b[3][2]; // 转置后行列大小互换 |
| 11 | for (int i = 0; i < 2; i++) |
| 12 | for (int j = 0; j < 3; j++) |
| 13 | b[j][i] = a[i][j]; // 行列下标互换写入 |
把本节内容汇总成几条最容易踩坑的规则:
matrix[i][j] 中 i 是行、j 是列,遍历时如果两层循环的边界写反(比如外层该跑行数却写成列数),要么越界访问,要么漏掉部分数据。养成"外层管行,内层管列"的固定习惯。int a[1000][1000] 就有 100 万个 int,占用约 4 MB,远超局部数组允许的栈空间。这类数组几乎总是需要定义成全局变量。a[i][j] 和 a[j][i],需要非常小心避免同一对元素被交换两次(抵消效果)或者行列数不相等时下标越界。初学阶段建议像上面的例子一样用一个新数组存放转置结果,逻辑更简单可靠。