矩阵是一种应用广泛的数据,今天看书学了矩阵的转置有关算法:
矩阵的转置主要可以分为两种:普通转置 O(n*m)与 快速转置 O(m+n)
(一)普通转置
首先定义矩阵存储的结构体
单个矩阵元素存储方式定义如下:
typedef struct{
int i,j;
int e;
}Triple;
矩阵整体定义:
typedef struct{
Triple data[MAXSIZE+1]; //索引下标从1开始算起
int mu,nu,tu; //存储矩阵的行数、列数、非零元个数
}TSMatrix;
然后矩阵转置算法:
//稀疏矩阵的转置操作
//按照矩阵M的列序进行转置
int TransposeSMatrix(TSMatrix M,TSMatrix &T){
T.nu=M.mu;T.mu=M.nu;T.tu=M.tu;
if(T.tu){
int q=1;
for(int col=1;col<=M.nu;col++)
for(int p=1;p<=M.tu;p++)
if(M.data[p].j==col){
T.data[q].i=M.data[p].j;
T.data[q].j=M.data[p].i;
T.data[q].e=M.data[p].e;
++q;
}
}
return 1;
}
第一种当然就没有这么完。。。在测试的时候,发现转置算法只对不含0的矩阵成功:
完整代码如下:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#define MAXSIZE 12500
typedef struct{
int i,j;
int e;
}Triple;
typedef struct{
Triple data[MAXSIZE+1];
int mu,nu,tu; //存储矩阵的行数、列数、非零元个数
}TSMatrix;
void input(TSMatrix &sm){
for(int i=1;i<=sm.nu*sm.mu;i++) //【1】如果普通的转置算法写成sm.mu*sm.nu,压缩矩阵则要把判定条件改为:i<=sm.tu
scanf("%d%d%d",&sm.data[i].i,&sm.data[i].j,&sm.data[i].e); //【2】注意要按照自己定义的结构体格式进行输入
}
void print(TSMatrix sm){
int index=1;
for(int i=1;i<=sm.mu;i++){
for(int j=1;j<=sm.nu;j++){
printf("%d\t",sm.data[index].e);
index++;
}
printf("\n");
}
}
//稀疏矩阵的转置操作
//按照矩阵M的列序进行转置
int TransposeSMatrix(TSMatrix M,TSMatrix &T){
T.nu=M.mu;T.mu=M.nu;T.tu=M.tu;
if(T.tu){
int q=1;
for(int col=1;col<=M.nu;col++)
for(int p=1;p<=M.tu;p++)
if(M.data[p].j==col){
T.data[q].i=M.data[p].j;
T.data[q].j=M.data[p].i;
T.data[q].e=M.data[p].e;
++q;
}
}
return 1;
}
int main(){
freopen("input1.txt","r",stdin);
freopen("input2.txt","r",stdin);
// printf("请输入矩阵的行数、列数、非零元素的个数:\n");
printf("原矩阵为:\n");
TSMatrix sm,ms;
scanf("%d%d%d",&sm.mu,&sm.nu,&sm.tu);
input(sm);
print(sm);
TransposeSMatrix(sm,ms);
printf("转置完:\n");
print(ms);
return 0;
}
测试实例:
input1.txt(m!=n)
2 3 6
1 1 1
1 2 2
1 3 0
2 1 4
2 2 0
2 3 6
input2.txt(m=n)
3 3 9
1 1 1
1 2 2
1 3 3
2 1 4
2 2 5
2 3 6
3 1 7
3 2 8
3 3 9
打印出来的效果是:
然鹅其实应该是:
但是本来书中介绍的重点是矩阵的压缩,即不为矩阵中的0元素分配存储空间。但是最初上面的方法还是消耗了存储“0”元素的存储空间。后来上网一看别人的代码,才发现自己误解了,虽然用自己的编写的输入输出函数实现了矩阵的转置操作,但是并没能实现矩阵的“压缩”。因此,算法问题还是要具体问题具体分析。不能带着做工程的思想去学算法,一开始总是很难建立一个全面的体系的,而要顺着思路往下走。学算法要尝试着先去接受它,熟悉它的应用场景,再尝试记忆。不懂的多用笔演算、多带入。这也算是今天的一大收获吧,花了将近两个小时找Bug……