快速转置法实现矩阵的转置
题目描述
请实现一个快速转置法来实现矩阵的转置。你将被给予一个矩阵,你需要输出该矩阵的转置。
输入格式
输入的第一行包含两个整数 n n n 和 m m m,分别代表矩阵的行数和列数 ( 1 ≤ n , m ≤ 100 ) (1 \leq n, m \leq 100) (1≤n,m≤100)。
接下来的 n n n 行,每行有 m m m 个整数,代表矩阵的元素。每个元素的绝对值不超过 1 0 9 10^9 109。
输出格式
输出 m m m 行,每行 n n n 个整数,代表转置后的矩阵。
样例 #1
样例输入 #1
3 3
1 0 0
0 0 5
3 0 0
样例输出 #1
1 0 3
0 0 0
0 5 0
样例 #2
样例输入 #2
6 7
0 12 9 0 0 0 0
0 0 0 0 0 0 0
-3 0 0 0 0 14 0
0 0 24 0 0 0 0
0 18 0 0 0 0 0
15 0 0 -7 0 0 0
样例输出 #2
0 0 -3 0 0 15
12 0 0 0 18 0
9 0 0 24 0 0
0 0 0 0 0 -7
0 0 0 0 0 0
0 0 14 0 0 0
0 0 0 0 0 0
思路
首先分配两个动态数组 num
和 cpot
,分别用于存储原矩阵每列非零元素的个数和转置矩阵每行下一个非零元素的位置。然后,通过遍历 M.data
数组来统计每列非零元素的个数,并计算出转置矩阵每行下一个非零元素的位置。
接下来,函数遍历 M.data
数组,根据每个非零元素的列号找到其在转置矩阵中的位置,并将其行号、列号和值存储到 T.data
数组中。在这个过程中,cpot[col]
(表示转置矩阵中列号为 col
的下一个非零元素的位置)会逐渐增加,以便于找到下一个元素的位置。
最后,释放 num
和 cpot
数组的内存。
算法分析
时间复杂度
函数执行过程中,主要进行了三次循环操作。第一次循环,遍历所有非零元素,用于统计每列非零元素的个数,时间复杂度为 O ( t ) O(t) O(t),其中 t t t 是非零元素的个数。第二次循环,遍历所有列,用于计算转置矩阵每行下一个非零元素的位置,时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是矩阵的列数。第三次循环,再次遍历所有非零元素,进行转置操作,时间复杂度为 O ( t ) O(t) O(t)。因此,总的时间复杂度为 O ( n + t ) O(n+t) O(n+t)。特别地,如果非零元素的个数 t t t 与矩阵的元素总数 m × n m \times n m×n 在同一个数量级,那么时间复杂度可以近似为 O ( m × n ) O(m \times n) O(m×n)。
空间复杂度
函数中分配了两个动态数组 num
和 cpot
,分别用于存储每列非零元素的个数和转置矩阵每行下一个非零元素的位置。因此,空间复杂度为
O
(
n
)
O(n)
O(n),其中
n
n
n 是矩阵的列数。
代码
#include <algorithm>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using Status = int;
using ElemType = int;
const int N = 1e4 + 7;
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int INFEASIBLE = -1;
// const int OVERFLOW = -2;
int n, m;
ElemType a[N][N];
struct Triple {
int i, j;
ElemType e;
};
struct TSMatrix {
Triple data[N];
int n, m;
int num; // 非零元个数
};
Status display(TSMatrix M) {
for (int i = 1; i <= M.m; i++) {
for (int j = 1; j <= M.n; j++) {
bool value = 0;
for (int k = 1; k <= M.num; k++) {
if (i == M.data[k].i && j == M.data[k].j) {
cout << M.data[k].e << " ";
value = 1;
break;
}
}
if (!value) {
cout << 0 << " ";
}
}
cout << "\n";
}
cout << "\n";
return OK;
}
Status add(TSMatrix &M, int i, int j, ElemType e) {
if (!e) {
return OK;
}
// cout << i << " " << j << " " << e << endl;
M.data[++M.num] = {i, j, e};
return OK;
}
Status fastTransposeSMatrix(TSMatrix M, TSMatrix &T) {
int p, q, col;
// M每列非零元素个数
int *num = (int *)malloc((M.n + 1) * sizeof(int));
if (!num) {
return ERROR;
}
// T每行下一个非零元素位置
int *cpot = (int *)malloc((M.n + 1) * sizeof(int));
if (!cpot) {
return ERROR;
}
T.m = M.n;
T.n = M.m;
T.num = M.num;
// 非零矩阵
if (T.num) {
// 初始化计数器
for (col = 1; col <= M.n; col++) {
num[col] = 0;
}
// 统计M每列非零元素个数
for (p = 1; p <= M.num; p++) {
num[M.data[p].j]++;
}
cpot[1] = 1;
// 求T每行下一个非零元素位置
for (col = 2; col <= M.n; col++) {
cpot[col] = cpot[col - 1] + num[col - 1];
}
// for (int i = 1; i <= M.n; i++) {
// cout << i << " " << num[i] << " " << cpot[i] << endl;
// }
for (p = 1; p <= M.num; p++) {
col = M.data[p].j;
q = cpot[col];
// cout << p << " " << col << " " << q << endl;
T.data[q].i = M.data[p].j;
T.data[q].j = M.data[p].i;
T.data[q].e = M.data[p].e;
cpot[col]++;
}
}
free(num);
free(cpot);
num = nullptr;
cpot = nullptr;
return OK;
}
int main() {
cin >> m >> n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
TSMatrix M;
M.n = n;
M.m = m;
M.num = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
add(M, i + 1, j + 1, a[i][j]);
}
}
// display(M);
TSMatrix T;
fastTransposeSMatrix(M, T);
display(T);
return 0;
}