在现实应用中,一些规模很大的特殊矩阵具有重要的地位。特殊矩阵可以采用二维数组存储,简单直接(顺序存储方式保持了矩阵中元素之间的二维线性关系),矩阵操作的算法都很简单,但是其空间的利用率很低(因为重复元素或零元素比较多)。 稀疏矩阵就是一种应用很广泛的特殊的矩阵,在实现稀疏矩阵ADT时通常采用“压缩”存储方案,即把只存储稀疏矩阵的非零元素,把稀疏矩阵抽象成为一个以三元组(行,列,值)为数据元素的线性表来处理,而我们知道:线性表可以采用顺序存储,也可以采用链式存储(通常用十字链表)。
现要求编程实现稀疏矩阵在“压缩”存储时的常用操作,如输出、转置、求和、乘等。(注:在代码注释中说明你采用的存储结构)
需要输入两个矩阵,完成:
(1) 转置。对第一个矩阵进行转置并输出,前面输出标题 “The transformed matrix is:”
(2) 矩阵加。如两个矩阵可以相加,进行两个矩阵加并输出,前面输出标题 “The added matrix is:”
如果不能相加输出 “Can not add!”;
(3) 矩阵乘。如果两个矩阵可以相乘,进行两个矩阵乘并输出,前面输出标题 “The product matrix is:”
如果不能相乘输出 “Can not multiply!”
矩阵的输入:有多行,第1行包括三个整数,分别是矩阵的大小m,n及非零元素的个数r。后面r行分别输入各个非零元素的 行、列、值。
矩阵的输出:有两种形式,操作时分别用符号“L”、“H”指出输出形式。
L: 以三元组的形式输出,即先输出矩阵的行数、列数和非零元素个数,再依次输出各个非零元素的行、列和值。
H: 按人们习惯的矩阵格式输出,即输出一个m*n的矩阵,是零元素的输出0,非零元素输出元素值。设定每个元素占位宽度为4。(要输出行号和列号,并对齐)
例如:输入如下:
10 8 4 //第1个矩阵 10行,8列,4个非零元素
1 8 1 //第1行第8列元素值为1
3 3 2 //第3行第3列元素值为2
3 7 3 //第3行第7列元素值为3
10 1 4 //第10行第1列元素值为4
10 8 2 //第2个矩阵 10行,8列,2个非零元素
2 6 1 //第2行第6列元素值为1
3 7 -3 //第3行第7列元素值为-3
H //输出格式类别
输出如下:
The transformed matrix is:
1 2 3 4 5 6 7 8 9 10
1 0 0 0 0 0 0 0 0 0 4
2 0 0 0 0 0 0 0 0 0 0
3 0 0 2 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 0 0
7 0 0 3 0 0 0 0 0 0 0
8 1 0 0 0 0 0 0 0 0 0
The added matrix is:
1 2 3 4 5 6 7 8
1 0 0 0 0 0 0 0 1
2 0 0 0 0 0 1 0 0
3 0 0 2 0 0 0 0 0
4 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0
8 0 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0 0
10 4 0 0 0 0 0 0 0
Can not multiply!
再如,输入矩阵如下:
100 90 5 //矩阵的行数为100,列数为90,共5个非零元素。
1 10 100 //a(1,10)=100
50 60 200 //a(50,60)=200
50 80 100 //a(50,80)=100
60 60 200 //a(60,60)=200
99 89 10 //a(99,89)=10
100 90 4 //矩阵b的行数为100,列数为90,共4个非零元素。
1 1 10 //b(1,1)=10
50 60 -200 //b(50,60)=-200
50 80 100 //b(50,80)=100
70 70 10 //b(70,70)=10
L
输出如下:
The transformed matrix is:
Rows=100,Cols=90,r=5
10 1 100
60 50 200
60 60 200
80 50 100
89 99 10
The added matrix is:
Rows=100,Cols=90,r=6
1 1 10
1 10 100
50 80 200
60 60 200
70 70 10
99 89 10
Can not multiply!
例如:
输入
100 90 5
1 10 100
50 60 200
50 80 100
60 60 200
99 89 10
100 90 4
1 1 10
50 60 -200
50 80 100
70 70 10
L
输出
The transformed matrix is:
Rows=90,Cols=100,r=5
10 1 100
60 50 200
60 60 200
80 50 100
89 99 10
The added matrix is:
Rows=100,Cols=90,r=6
1 1 10
1 10 100
50 80 200
60 60 200
70 70 10
99 89 10
Can not multiply!
稀疏矩阵的乘法搞了好久仍没搞出来,最后参考了把三元组转换为矩阵再相乘的方法才做出来(感觉并不是很符合要求)
#include<cstdio>
using namespace std;
typedef struct triple//顺序存储
{
int row;
int col;
int val;
}element;
void Swap(element &a,element &b)//交换两个元素,用在排序中
{
element t=a;
a=b;
b=t;
}
class matrix//矩阵类
{
private:
element e[505];//矩阵元素
int rows;//行,private型
int cols;//列,private型
int r;//元素个数,private型
int m[505][505];
public:
void create();//创建矩阵
void trans(matrix a);//求矩阵的转置
void add(matrix a,matrix b);//求两个矩阵相加
void mul(matrix a,matrix b);//求两个矩阵相乘
void show_l();//按习惯的矩阵格式输出
void show_h();//按三元组的形式输出
int getrows();//获取矩阵的行数
int getcols();//获取矩阵的列数
int getr();//获取矩阵的元素
void transmatrix();
};
int matrix::getrows()
{
return rows;
}
int matrix::getcols()
{
return cols;
}
int matrix::getr()
{
return r;
}
void matrix::create()
{
scanf("%d %d %d",&rows,&cols,&r);
for(int i=1;i<=r;i++)
{
scanf("%d %d %d",&e[i].row,&e[i].col,&e[i].val);
}
}
void matrix::trans(matrix a)//求矩阵的转置
{
rows=a.cols;
cols=a.rows;
r=a.r;
for(int i=1;i<=r;i++)
{
e[i].col=a.e[i].row;
e[i].row=a.e[i].col;
e[i].val=a.e[i].val;
}
for(int i=1;i<=r-1;i++)//按行升序排序,行相同时按列升序排序
{
for(int j=i+1;j<=r;j++)
{
if(e[i].row>e[j].row)Swap(e[i],e[j]);
else if(e[i].row==e[j].row)
{
if(e[i].col>e[j].col)Swap(e[i],e[j]);
}
}
}
}
void matrix::add(matrix a,matrix b)//求两个矩阵相加
{
rows=a.rows;
cols=a.cols;
int i=1,j=1,k=1;
for(i=1;i<=a.r;i++)
{
for(j=1;j<=b.r;j++)
{
if(a.e[i].row==b.e[j].row&&a.e[i].col==b.e[j].col)//先找有无相等的元素位置
{
if(a.e[i].val+b.e[j].val!=0)//相加的和不为0的情况。此时表示找到
{
e[k].row=a.e[i].row;
e[k].col=a.e[i].col;
e[k].val=a.e[i].val+b.e[j].val;
k++;
}
break;
}
}
if(j==b.r+1)//没找到,说明没有与第i个元素位置相等的元素
{
e[k].row=a.e[i].row;
e[k].col=a.e[i].col;
e[k].val=a.e[i].val;
k++;
}
}
for(i=1;i<=b.r;i++)//找a,b矩阵中元素位置不同的元素
{
for(j=1;j<=a.r;j++)
{
if(a.e[j].row==b.e[i].row&&a.e[j].col==b.e[i].col)break;
}
if(j==a.r+1)
{
e[k].row=b.e[i].row;
e[k].col=b.e[i].col;
e[k].val=b.e[i].val;
k++;
}
}
r=k-1;//记录保留下来的元素个数
for(i=1;i<=r-1;i++)//按行升序排序,行相同时按列升序排序
{
for(j=i+1;j<=r;j++)
{
if(e[i].row>e[j].row)Swap(e[i],e[j]);
else if(e[i].row==e[j].row)
{
if(e[i].col>e[j].col)Swap(e[i],e[j]);
}
}
}
}
void matrix::transmatrix()//转换成非稀疏矩阵
{
for(int i=1;i<=rows;i++)
{
for(int j=1;j<=cols;j++)
{
m[i][j]=0;
}
}
for(int i=1;i<=r;i++)
{
m[e[i].row][e[i].col]=e[i].val;
}
}
void matrix::mul(matrix a,matrix b)//矩阵相乘
{
rows=a.rows;
cols=b.cols;
for(int i=1;i<=a.r-1;i++)//按行升序排序,行相同时按列升序排序
{
for(int j=i+1;j<=a.r;j++)
{
if(a.e[i].row>a.e[j].row)Swap(a.e[i],a.e[j]);
else if(a.e[i].row==a.e[j].row)
{
if(a.e[i].col>a.e[j].col)Swap(a.e[i],a.e[j]);
}
}
}
for(int i=1;i<=b.r-1;i++)//按列升序排序,列相同时按行升序排序
{
for(int j=i+1;j<=b.r;j++)
{
if(b.e[i].col>b.e[j].col)Swap(b.e[i],b.e[j]);
else if(b.e[i].col==b.e[j].col)
{
if(b.e[i].row>b.e[j].row)Swap(b.e[i],b.e[j]);
}
}
}
int sum,t=1;
a.transmatrix();
b.transmatrix();
for(int i=1;i<=a.rows;i++)//矩阵相乘
{
for(int j=1;j<=b.cols;j++)
{
sum=0;//求第i行第j列的所有非0元素和
for(int k=1;k<=a.cols;k++)
{
sum+=a.m[i][k]*b.m[k][j];
}
if(sum!=0)
{
e[t].row=i;
e[t].col=j;
e[t].val=sum;
t++;
}
}
}
r=t-1;//记录保留下来的元素个数
for(int i=1;i<=r-1;i++)
{
for(int j=i+1;j<=r;j++)//按行升序排序,行相同时按列升序排序
{
if(e[i].row>e[j].row)Swap(e[i],e[j]);
else if(e[i].row==e[j].row)
{
if(e[i].col>e[j].col)Swap(e[i],e[j]);
}
}
}
}
void matrix::show_h()
{
int i,j,k,zero=0;
printf(" ");
for(i=1;i<=cols;i++)
{
printf("%4d",i);
}
printf("\n");
for(i=1;i<=rows;i++)
{
printf("%4d",i);
for(j=1;j<=cols;j++)
{
for(k=1;k<=r;k++)
{
if(e[k].row==i&&e[k].col==j)//坐标(i,j)出现在所有非0元素中
{
printf("%4d",e[k].val);
break;
}
}
if(k==r+1)printf("%4d",zero);//没有出现,就输出0
}
printf("\n");
}
}
void matrix::show_l()
{
for(int i=1;i<=r;i++)
{
printf("%d %d %d\n",e[i].row,e[i].col,e[i].val);
}
}
matrix m1,m2,mtrans,madd,mmul;
int main()
{
char ss[5];
m1.create();
m2.create();
mtrans.trans(m1);//转置
madd.add(m1,m2);//相加
mmul.mul(m1,m2);//相乘
scanf("%s",ss);
if(ss[0]=='H')
{
printf("The transformed matrix is:\n");
mtrans.show_h();
if(m1.getrows()==m2.getrows()&&m1.getcols()==m2.getcols())
{
printf("The added matrix is:\n");
madd.show_h();
}
else printf("Can not add!\n");
if(m1.getcols()==m2.getrows())
{
printf("The product matrix is:\n");
mmul.show_h();
}
else printf("Can not multiply!\n");
}
else if(ss[0]=='L')
{
printf("The transformed matrix is:\n");
printf("Rows=%d,Cols=%d,r=%d\n",mtrans.getrows(),mtrans.getcols(),mtrans.getr());
mtrans.show_l();
if(m1.getrows()==m2.getrows()&&m1.getcols()==m2.getcols())
{
printf("The added matrix is:\n");
printf("Rows=%d,Cols=%d,r=%d\n",madd.getrows(),madd.getcols(),madd.getr());
madd.show_l();
}
else printf("Can not add!\n");
if(m1.getcols()==m2.getrows())
{
printf("The product matrix is:\n");
printf("Rows=%d,Cols=%d,r=%d\n",mmul.getrows(),mmul.getcols(),mmul.getr());
mmul.show_l();
}
else printf("Can not multiply!\n");
}
return 0;
}