1.实验内容
创建稀疏矩阵类,采用行主顺序把稀疏矩阵非0元素映射到一维数组中,实现操作:两个稀疏矩阵相加、两个稀疏矩阵相乘、稀疏矩阵的转置、输出矩阵。
重置矩阵:操作1,即重置矩阵P的尺寸为n行m列,且随后按行优先顺序输入矩阵P的各个元素。
矩阵乘法:操作2,t行非零元素已按行优先顺序给出,矩阵中非零元素的表示为x y v,其中x表示行序号,y表示列序号,v表示非零元素值,行列序号从1开始。设输入的矩阵为Q,若P×Q运算合法,则将P×Q的结果矩阵赋给P,若不合法,则将Q赋给P,同时输出-1。
矩阵加法:操作3,t行非零元素已按行优先顺序给出,矩阵中非零元素的表示为x y v,其中x表示行序号,y表示列序号,v表示非零元素值,行列序号从1开始。设输入的矩阵为 Q,若P+Q运算合法,则将P+Q的结果矩阵赋给P,若不合法,则将Q赋给P,同时输出 -1。
输出操作:操作4,设当前矩阵P的尺寸为n行m列,第一行输出矩阵P的行数和列数,随后n行按行优先顺序输出矩阵P,每行m个数字,来表示当前的矩阵内容每行数字之间用空格分隔。
转置操作:操作5,设当前矩阵P的尺寸为n行m列,将其转置为m 行n列的矩阵,无需输出。
输入输出格式:
输入:
第一行一个w代表操作个数,接下来若干行是各个操作,其中保证第一个操作一定为重置矩阵。
输出:
当执行操作4时,输出矩阵P;当执行操作2或3时,若对应运算不合法,则输出-1。
2.测试结果
输入:
10
1
3 3
1 2 3
4 5 6
7 8 9
4
5
4
3
3 3
2
1 1 -1
2 1 7
4
2
3 3
3
1 1 1
2 2 1
3 3 1
4
3
2 2
4
1 1 -1
1 2 -2
2 1 -3
2 2 -4
4
输出:
3 3
1 2 3
4 5 6
7 8 9
3 3
1 4 7
2 5 8
3 6 9
3 3
0 4 7
9 5 8
3 6 9
3 3
0 4 7
9 5 8
3 6 9
-1
2 2
-1 -2
-3 -4
3.源代码
#include<iostream>
using namespace std;
template<class T>
struct matrixTerm //稀疏矩阵中元素的三要素
{
int row;
int col;
T value;
matrixTerm& operator=(matrixTerm& x){row=x.row;col=x.cow;value=x.value;return *this;}
};
template<class T>
class sparseMatrix
{
public:
sparseMatrix(int &m,int &n)//构造函数(m为行数,n为列数,terms为非零元素个数)
{
rows=m;
cols=n;
terms=0;
termsArray=new matrixTerm<T>[m*n];
}
~sparseMatrix() //析构函数
{
delete []termsArray;
}
void changeSize(int m,int n) //改变矩阵大小
{
delete []termsArray;
rows=m;
cols=n;
terms=0;
termsArray=new matrixTerm<T>[m*n];
}
void sparseMatrixCopy(sparseMatrix<T> &A) //复制稀疏矩阵
{
delete []termsArray;
rows=A.rows;
cols=A.cols;
terms=A.terms;
termsArray=new matrixTerm<T>[terms];
for(int i=0;i<terms;i++)
{
termsArray[i].row=A.termsArray[i].row;
termsArray[i].col=A.termsArray[i].col;
termsArray[i].value=A.termsArray[i].value;
}
}
void inPut() //依次输入矩阵内的所有元素
{
T addValue;
int addTerms=0;
for(int i=0;i<rows*cols;i++)
{
cin>>addValue;
if(addValue!=0)
{
termsArray[terms].value=addValue;
termsArray[terms].col=i-(i/cols)*cols+1;
termsArray[terms].row=i/cols+1;
terms++;
}
}
}
void inPut2() //依次输入所有非0元素的三要素
{
int t;
cin>>t;
for(int i=0;i<t;i++)
{
int addRow,addCol;
T addValue;
cin>>addRow>>addCol>>addValue;
termsArray[i].value=addValue;
termsArray[i].col=addCol;
termsArray[i].row=addRow;
terms++;
}
}
void transpose() //矩阵转置
{
sparseMatrix<T> C(cols,rows);
int num[cols]; //数组num记录每一列(0至col-1)的非0元素个数
for(int i=0;i<cols;i++)
num[i]=0;
for(int i=0;i<terms;i++)
++num[termsArray[i].col-1];
int cpot[cols];
//数组cpot记录每一列(1至col)与之前所有列的非0元素个数之和
cpot[0]=0;
for(int i=1;i<cols;i++)
cpot[i]=cpot[i-1]+num[i-1];
for(int p=0;p<terms;p++) //将第p个非0元素存入C中
{
int col=termsArray[p].col-1;
int q=cpot[col];
C.termsArray[q].col=termsArray[p].row;
C.termsArray[q].row=termsArray[p].col;
C.termsArray[q].value=termsArray[p].value;
cpot[col]++;
}
C.terms=terms;
sparseMatrixCopy(C); //把C复制给此矩阵
}
void outPut() //输出矩阵
{
int k=0;
cout<<rows<<" "<<cols<<endl;
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(k<terms && termsArray[k].row==i+1 && termsArray[k].col==j+1)
cout<<termsArray[k++].value<<" ";
else
cout<<0<<" ";
}
cout<<endl;
}
}
void multiply(sparseMatrix<T> &B) //矩阵乘法
{
if(cols!=B.rows) //矩阵乘法不合法
{
sparseMatrixCopy(B); //将实参矩阵赋给此矩阵
cout<<-1<<endl; //输出-1
}
else
{
sparseMatrix<T> C(rows,B.cols);
B.transpose(); //将B转置
int it=0,ib=0;
//it为此矩阵中已取的非0元素个数,ib为B中已去的非0元素个数
for(int i=0;i<rows;i++)
//求C中第i行(0至rows-1)第j列(0至B.cols-1)的元素
{
int flag=it;
ib=0;
for(int j=0;j<B.rows;j++)
{
int num=0; //num为这个元素的值
it=flag;
while(termsArray[it].row==i+1 && B.termsArray[ib].row==j+1) //此矩阵读取到第i行(1至rows),B读取到第j行(1至B.cols)
{
if(termsArray[it].col<B.termsArray[ib].col)
//此矩阵当前读取的非0元素的列小于B当前读取的非0元素的列,此矩阵读取坐标后移
it++;
else if(termsArray[it].col>B.termsArray[ib].col)
//此矩阵当前读取的非0元素的列大于B当前读取的非0元素的列,B读取坐标后移
ib++;
else
//此矩阵当前读取的非0元素的列等于B当前读取的非0元素的列,计算二者的积加入num,读取坐标均后移
{
num+=termsArray[it].value*B.termsArray[ib].value;
it++;
ib++;
}
}
while(termsArray[it].row==i+2 && B.termsArray[ib].row==j+1) //此矩阵当前读取的非0元素已属于下一行,将B的读取坐标也移至下一行
ib++;
while(termsArray[it].row==i+1 && B.termsArray[ib].row==j+2) //B当前读取的非0元素已属于下一行,将此矩阵的读取坐标也移至下一行
it++;
if(num!=0) //如果C中第i行第j列的元素不为0,将值记入C.termsArray
{
C.termsArray[C.terms].row=i+1;
C.termsArray[C.terms].col=j+1;
C.termsArray[C.terms].value=num;
C.terms++;
}
}
}
sparseMatrixCopy(C); //把C复制给此矩阵
}
}
void add(sparseMatrix<T> &B) //矩阵加法
{
if(rows!=B.rows || cols!=B.cols) //矩阵加法不合法
{
sparseMatrixCopy(B); //将实参矩阵赋给此矩阵
cout<<-1<<endl; //输出-1
}
else
{
sparseMatrix<T> C(rows,cols); //用稀疏矩阵C
int it=0,ib=0;
//it记录此矩阵中已取的非0元素个数,ib记录B中已取的非0元素个数
while(it!=terms && ib!=B.terms) //此矩阵和B中的非0元素都未取完时
{
int tIndex=(termsArray[it]).row*cols+(termsArray[it]).col;
//此矩阵中下一个未取到的非0元素在矩阵中的一维位置
int bIndex=(B.termsArray[ib]).row*cols+(B.termsArray[ib]).col;
//B中下一个未取到的非0元素在矩阵中的一维位置
if(tIndex<bIndex)
//当此矩阵当前一维位置较小时,插入该矩阵中的当前元素
{
C.termsArray[C.terms].col=termsArray[it].col;
C.termsArray[C.terms].row=termsArray[it].row;
C.termsArray[C.terms].value=termsArray[it].value;
it++;
C.terms++;
}
else if(tIndex==bIndex)
//当此矩阵与B当前一维位置相同时,若和不为0,插入二者之和,若和为0,跳过这两个位置
{
if((termsArray[it]).value+(B.termsArray[ib]).value!=0)
{
C.termsArray[C.terms].col=(termsArray[it]).col;
C.termsArray[C.terms].row=(termsArray[it]).row;
C.termsArray[C.terms].value=(termsArray[it]).value+(B.termsArray[ib]).value;
C.terms++;
}
it++;
ib++;
}
else //当B当前一维位置较小时,插入B中的当前元素
{
C.termsArray[C.terms].col=B.termsArray[ib].col;
C.termsArray[C.terms].row=B.termsArray[ib].row;
C.termsArray[C.terms].value=B.termsArray[ib].value;
ib++;
C.terms++;
}
}
for(;it!=terms;it++) //继续取此矩阵中未取完的非0元素
{
C.termsArray[C.terms].col=termsArray[it].col;
C.termsArray[C.terms].row=termsArray[it].row;
C.termsArray[C.terms].value=termsArray[it].value;
C.terms++;
}
for(;ib!=B.terms;ib++) //继续取B中未取完的非0元素
{
C.termsArray[C.terms].col=B.termsArray[ib].col;
C.termsArray[C.terms].row=B.termsArray[ib].row;
C.termsArray[C.terms].value=B.termsArray[ib].value;
C.terms++;
}
sparseMatrixCopy(C); //把C复制给此矩阵
}
}
private:
int rows;
int cols;
int terms;
matrixTerm<T>* termsArray;
};
int main()
{
int w; //输入操作次数
cin>>w;
int op;
cin>>op; //输入操作类型
op=1; //强制第1次操作为重置矩阵
int m,n;
cin>>m>>n; //输入矩阵的行数和列数
sparseMatrix<int> M(m,n);
sparseMatrix<int> N(m,n);
M.inPut(); //输入矩阵的所有元素
for(int i=0;i<w-1;i++) //进行w-1次操作
{
cin>>op; //输入操作类型
switch(op)
{
case 1: //重置矩阵
cin>>m>>n; //输入重置后的行数和列数
N.changeSize(m,n); //将N重置为m行n列
N.inPut(); //输入N的所有元素
M.sparseMatrixCopy(N); //将N赋值给M
break;
case 2: //矩阵乘法
cin>>m>>n; //输入右矩阵的行数和列数
N.changeSize(m,n); //将N重置为m行n列
N.inPut2(); //输入N的非0元素
M.multiply(N); //将N右乘入M
break;
case 3: //矩阵加法
cin>>m>>n; //输入右矩阵的行数和列数
N.changeSize(m,n); //将N重置为m行n列
N.inPut2(); //输入N的非0元素
M.add(N); //将N加入M
break;
case 4: //输出矩阵
M.outPut();
break;
case 5: //转置矩阵
M.transpose();
break;
default:
break;
}
}
return 0;
}