非方阵转置必须新建矩阵,仅方阵可原地交换;推荐用vector避免内存泄漏和维度错误,注意行列下标互换及循环顺序。

转置必须新建矩阵,原地交换只适用于方阵
非方阵(比如 3x4)根本没法在原数组里完成转置——目标尺寸是 4x3,内存布局和容量都不匹配。强行用指针“模拟”只会越界或覆盖数据。只有 n x n 方阵才能考虑原地算法,且需严格按对角线以下(或以上)元素逐个交换。
实操建议:
- 通用场景一律申请新矩阵:
vector<vector>> result(cols, vector<int>(rows));</int></vector> - 方阵原地转置时,循环范围必须是
i = 0 to n-1,j = i+1 to n-1,否则会重复交换回原样 - 用
swap(matrix[i][j], matrix[j][i]);而不是赋值语句,避免中间变量出错
用 vector> 还是 T**?优先选前者
vector<vector>></vector> 内存不连续,但安全、可直接获取行列尺寸(mat.size() 和 mat[0].size()),适合教学和一般工程;int** 需手动 new/delete,易泄漏,且无法从指针反推维度——传参时必须额外带 rows 和 cols 参数。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 对
int** mat直接调用sizeof(mat)想算列数 → 结果永远是 8(指针大小) - 释放
int**时只delete[] mat,漏掉每行的delete[] mat[i]→ 内存泄漏 - 初始化
vector<vector>></vector>时写成vector<vector>>(rows, cols)</vector>→ 编译失败,正确是vector<vector>>(rows, vector<int>(cols))</int></vector>
转置后访问越界?检查索引方向是否翻转
原始矩阵 mat[i][j] 对应第 i 行、第 j 列;转置后该元素应落在 result[j][i] —— 行列下标必须互换。最容易错的是循环嵌套顺序:外层遍历原列(即新行),内层遍历原行(即新列)。
示例(正确):
for (int j = 0; j < cols; ++j) { // 新矩阵的行 = 原矩阵的列
for (int i = 0; i < rows; ++i) { // 新矩阵的列 = 原矩阵的行
result[j][i] = mat[i][j];
}
}如果把两个循环顺序写反,或者下标没同步改,就会出现 result[i][j] = mat[i][j] 这类无效赋值,结果全是零或随机值。
性能敏感场景别忽略 cache 友好性
上面的双重循环按列优先遍历原矩阵(mat[i][j] 中 i 是外层),会导致 CPU cache miss 频发——因为 mat 是行主序存储,跨行访问跳着读内存。对大矩阵(如 >1000x1000),这可能慢 3–5 倍。
优化方法(仅当实测瓶颈在此时采用):
- 分块转置(tiling):每次处理
16x16小块,提升局部性 - 用一维数组模拟二维:
mat[i * cols + j],配合循环重排,便于编译器向量化 - 确认是否真需要完整转置——有时等价改写算法逻辑(比如把乘法顺序从
A * B换成B^T * A^T)比实际转更快
绝大多数业务代码不用管这个,但如果你在写图像处理或科学计算底层,第一次跑 5000x5000 矩阵就卡住,回头看看循环顺序和内存访问模式。


















