转置操作本质是matrixi→matrixj,即行列索引互换;必须用swap避免数据覆盖,非方阵不可原地转置。

转置操作本质是 matrix[i][j] → matrix[j][i]
二维数组转置不是“旋转”,而是行列索引互换:原第 i 行第 j 列的值,变成新矩阵第 j 行第 i 列的值。这个映射关系必须严格遵守,否则结果错位。
常见错误现象包括:
- 循环边界写反(比如用
for (j=0; j<rows> 去遍历列)</rows> - 目标数组维度没按
cols × rows分配,导致越界或截断 - 原地操作时未限制为方阵,强行交换引发覆盖
固定大小数组用嵌套循环直接赋值
编译期已知尺寸(如 int a[4][5]),最简单方式是声明目标数组并双层循环赋值。
关键点:
立即学习“C++免费学习笔记(深入)”;
- 目标数组声明必须是
int trans[5][4](列数在前,行数在后) - 内层循环变量控制源列,外层控制源行;赋值语句固定为
trans[j][i] = a[i][j] - 不能复用同一块内存(比如把
a当作输出数组),除非是方阵且用原地法
示例片段:
#include <iostream>
int main() {
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int trans[4][3]; // 注意维度翻转
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 4; ++j)
trans[j][i] = a[i][j];
}
std::vector<std::vector<int>> 转置需重新构造维度
动态尺寸下不能只改指针或 reinterpret_cast,必须新建 vector 并按新行列数 resize。
实操要点:
- 先检查输入是否为空:
if (mat.empty() || mat[0].empty()) - 目标容器初始化为
vector<vector>>(cols, vector<int>(rows))</int></vector> - 避免用
push_back动态追加——会破坏连续性,影响后续访问性能 - 若原矩阵每行长度不一致(非矩形),需额外校验或抛异常
典型函数签名:
vector<vector<int>> transpose(const vector<vector<int>>& mat) {
if (mat.empty()) return {};
size_t rows = mat.size(), cols = mat[0].size();
vector<vector<int>> res(cols, vector<int>(rows));
for (size_t i = 0; i < rows; ++i)
for (size_t j = 0; j < cols; ++j)
res[j][i] = mat[i][j];
return res;
}
方阵可用原地交换节省空间
仅当 rows == cols 时成立,否则索引越界或逻辑错误。
核心技巧:
- 只遍历上三角(
j > i),避免重复交换和自交换 - 用
swap(matrix[i][j], matrix[j][i]),不是赋值 - 切记不能用临时变量逐个赋值再覆盖——顺序错会导致数据丢失
错误写法示例(会导致第一轮就污染数据):
// ❌ 错误 temp = matrix[i][j]; matrix[i][j] = matrix[j][i]; // 此时 matrix[j][i] 已被覆盖 matrix[j][i] = temp; // 写回的是旧值?不,是刚被覆盖的新值
正确做法始终用 std::swap 或等价的三步交换。
最容易被忽略的是:非方阵无法原地转置。哪怕只差一行一列,也必须分配新内存——强行复用原数组会触发未定义行为,调试时可能表现为部分值不变、部分全零或随机值。


















