一道简单的数据结构题目。题目描述如下:
特殊矩阵在采用二维数组存储时,尽管矩阵操作的算法都很简单,但是其空间的利用率很低。 系数矩阵就是一种应用很广泛的特殊的矩阵。现要求稀疏矩阵采用“压缩”存储,实现矩阵的常用操作,如输出、转置、求和等。
矩阵的输入:有多行,第1行包括三个整数,分别是矩阵的大小m,n及非零元素的个数r。
后面r行分别输入各个非零元素的 行、列、值
矩阵的输出:按人们习惯的矩阵格式输出,即输出一个m*n的矩阵,是零元素的输出0,非零元素输出元素值。
例如:输入如下:
输入 | Result |
---|---|
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 | The transformed matrix is: 10 1 100 60 50 200 60 60 200 80 50 100 89 99 10 The added matrix is: 1 1 10 1 10 100 50 80 200 60 60 200 70 70 10 99 89 10 |
这道题比较简单,只输入两个稀疏矩阵,要求对第一个矩阵进行转置,对两个矩阵相加。
在计算机中存储矩阵一般都用二位数组,它的有点是可以随机访问每一个元素,缺点是如果输入的是特殊矩阵(如稀疏矩阵)会造成大量的空间浪费,而且对于某些需要遍历矩阵的算法来说会耗费大量的时间,显然是不可取的。所以,对于稀疏矩阵,必须考虑对其压缩存储。一种较好的方法是:只存储在矩阵中极少的非零元素,为此,必须对每一个非零元素保存其下标和值。可以采用一个三元组<row,column,value>来唯一的确定一个矩阵元素,因此,稀疏矩阵需要用一个三元组数组来表示。在该数组中,个矩阵元素的三元组按在原矩阵中的位置,以行优先的规则依次存放,另外还要存储原矩阵的行数、列数和非零元素的个数。以上是稀疏矩阵的定义和存储。对于系数矩阵的转置,可以新定义一个三元组表,将新定义的三元组表的行数和列数与目标矩阵的列数和行数互换,value的值不变,假设原三元组表有cols列,当cols列扫描完成,算法结束;两个矩阵相加,其前提条件是两个矩阵大小相同,即行数和列数相同,本题不存在行数和列数不相同的问题。矩阵的加法,各位朋友可以去问度娘,当然输出需要按照行的大小进行排列然后输出。
完整代码如下:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
struct Trituple{//三元组结构体
int row,col;
int value;
};
class SparseMatrix{//三元组表类
public:
int Rows,Cols,Terms;
Trituple *thArray;
public:
SparseMatrix(int x,int y,int z);
SparseMatrix(){thArray = new Trituple[1001];}
~SparseMatrix(){delete[] thArray;}
void Transpose();//转置函数
void Add(SparseMatrix &b);//矩阵相加函数
};
void SparseMatrix::Add(SparseMatrix &b){
SparseMatrix result;
result.Rows = Rows;
result.Cols = Cols;
result.Terms = 0;
int i=0,j=0,index_a,index_b;
while(i<Terms&&j<b.Terms){
/*
用index_a和index_b来比较里两个元素在原矩阵中的位置,因为矩阵大小相同,实际上这比的是
两个元素谁更靠前
*/
index_a = Cols*thArray[i].row + thArray[i].col;
index_b = Cols*b.thArray[j].row + b.thArray[j].col;
if(index_a<index_b){
result.thArray[result.Terms] = thArray[i];
i++;
}
else if(index_a>index_b){
result.thArray[result.Terms] = b.thArray[j];
j++;
}
else{
if((thArray[i].value + b.thArray[j].value)!=0){
result.thArray[result.Terms] = thArray[i];
result.thArray[result.Terms].value = thArray[i].value + b.thArray[j].value;
i++;j++;
}
//else的意思是存在两个value相加为零的情况,如果为零则继续循环,Terms不用加1
else{i++;j++;continue;}
}
result.Terms++;
}
//复制剩余的元素
for(;i<Terms;i++){
result.thArray[result.Terms] = thArray[i];
result.Terms++;
}
for(;j<b.Terms;j++){
result.thArray[result.Terms] = b.thArray[j];
result.Terms++;
}
//输出结果
printf("The added matrix is:\n");
for(int i=0;i<result.Terms;i++){
printf("%d %d %d\n",result.thArray[i].row,result.thArray[i].col,result.thArray[i].value);
}
}
//构造函数赋初值,将矩阵的行数、列数以及非零元素的个数赋给相应的成员变量
SparseMatrix::SparseMatrix(int x,int y,int z){
Rows = x;Cols = y;Terms = z;
thArray = new Trituple[z+1];
}
//实现转置函数
void SparseMatrix::Transpose(){
SparseMatrix b(Cols,Rows,Terms);
int k,i,CurrentB=0;
for(k=0;k<Cols;k++){
for(i=0;i<Terms;i++){
if(thArray[i].col==k){
b.thArray[CurrentB].row = k;
b.thArray[CurrentB].col = thArray[i].row;
b.thArray[CurrentB].value = thArray[i].value;
CurrentB++;
}
}
}
//输出结果
printf("The transformed matrix is:\n");
for(i=0;i<Terms;i++){
printf("%d %d %d\n",b.thArray[i].row,b.thArray[i].col,b.thArray[i].value);
}
}
int main()
{
int m1,n1,r1,m2,r2,n2;
scanf("%d %d %d",&m1,&n1,&r1);
SparseMatrix a(m1,n1,r1);
for(int i=0;i<a.Terms;i++){
scanf("%d %d %d",&a.thArray[i].row,&a.thArray[i].col,&a.thArray[i].value);
}
scanf("%d %d %d",&m2,&n2,&r2);
SparseMatrix b(m2,n2,r2);
for(int j=0;j<b.Terms;j++){
scanf("%d %d %d",&b.thArray[j].row,&b.thArray[j].col,&b.thArray[j].value);
}
a.Transpose();
a.Add(b);
return 0;
}
有不明白的问题可以在下方留言哦,也欢迎各位朋友批评指正代码中不正确的地方。