稀疏矩阵类(以三列二维数组表示)
这是一个用三列二维数组表示的稀疏矩阵类。
这里将类与主函数放在一起以便于阅读,如有其他需要请自行封装。
运行结果及源码在下方给出。
注:蓝色下划线需要通过键盘键入

//稀疏矩阵类(以三列二维数组表示) #include<iostream> #include<iomanip> using namespace std; //定义结点类型 template<class T> struct B { int i; //非零元素所在的行号 int j; //非零元素所在的列号 T v; //非零元素值 }; //三列二维数组表示的稀疏矩阵类 template<class T> //类模板,T为虚拟类型 class X_Array { private: //数据成员 int mm; //稀疏矩阵行数 int nn; //稀疏矩阵列数 int tt; //稀疏矩阵中非零元素个数 B<T> *bb; //三列二维数组空间 int *pos; //某行第一个非零元素在b中的下标 int *num; //某行非零元素的个数 public: //成员函数 void in_X_Array(); //以三元组形式键盘输入稀疏矩阵非零元素 void cp_X_Array(int,int,int,B<T>[]);//复制三元组数组 void th_X_Array(int,int,T []);//由一般稀疏矩阵转换 void prt_X_Array(); //按行输出稀疏矩阵 X_Array tran_X_Array(); //稀疏矩阵转置 X_Array operator + (X_Array &);//稀疏矩阵相加 X_Array operator * (X_Array &);//稀疏矩阵相乘 }; //以三元组形式从键盘输入稀疏矩阵非零元素 template<class T> //函数模板,T为虚拟类型 void X_Array<T>::in_X_Array() { int k,m,n; cout<<"输入函数 列数 非零元素个数:"; cin>>mm>>nn>>tt; bb=new B<T> [tt]; //申请三列二维数组空间 cout<<"输入行数 列号 非零元素值:"<<endl; for (k=0;k<tt;k++) //输入三元组 { cin>>m>>n>>bb[k].v; bb[k].i=m-1; bb[k].j=n-1; } pos=new int[mm]; //申请POS向量空间 num=new int[mm]; //申请NUM向量空间 for(k=0;k<mm;k++) //NUM向量初始化 num[k]=0; for(k=0;k<tt;k++) //构造NUM向量 num[bb[k].i]=num[bb[k].i]+1; pos[0]=0; for(k=1;k<mm;k++) //构造POS向量 pos[k]=pos[k-1]+num[k-1]; return; } //复制三元组数组 template<class T> //函数模板,T为虚拟类型 void X_Array<T>::cp_X_Array(int m,int n,int t,B<T> b[]) { int k; mm=m;nn=n;tt=t; //复制稀疏矩阵的行号、列号和非零元素个数 bb=new B<T> [tt]; //申请三列二维数组空间 for(k=0;k<t;k++) //复制三列二维数组 { bb[k].i=b[k].i-1; bb[k].j=b[k].j-1; bb[k].v=b[k].v; } pos=new int[mm]; //申请POS向量空间 num=new int[mm]; //申请NUM向量空间 for(k=0;k<mm;k++) //NUM向量初始化 num[k]=0; for(k=0;k<tt;k++) //构造NUM向量 num[bb[k].i]=num[bb[k].i]+1; pos[0]=0; for(k=1;k<mm;k++) //构造POS向量 pos[k]=pos[k-1]+num[k-1]; return; } //由一般稀疏矩阵转换 template<class T> //函数模板,T为虚拟类型 void X_Array<T>::th_X_Array(int m,int n,T a[]) { int k,t=0,p,q; T d; for(k=0;k<m*n;k++) //统计非零元素个数 if(a[k]!=0)t=t+1; mm=n;nn=n;tt=t; bb=new B<T> [tt]; //申请三列二维数组空间 k=0; for(p=0;p<m;p++) for(q=0;q<n;q++) { d=a[p*n+q]; if(d!=0) //非零元素 { bb[k].i=p; bb[k].j=q; bb[k].v=d; k=k+1; } } pos=new int[mm]; //申请POS向量空间 num=new int[mm]; //申请NUM向量空间 for(k=0;k<mm;k++) //NUM向量初始化 num[k]=0; for(k=0;k<tt;k++) //构造NUM向量 num[bb[k].i]=num[bb[k].i]+1; pos[0]=0; for(k=1;k<mm;k++) //构造POS向量 pos[k]=pos[k-1]+num[k-1]; return; } //按行输出稀疏矩阵 template<class T> //函数模板,T为虚拟函数 void X_Array<T>::prt_X_Array() { int k,kk,p; for(k=0;k<mm;k++) //按行输出 { p=pos[k]; for(kk=0;kk<nn;kk++) //输出一行 if((bb[p].i==k) && (bb[p].j==kk))//输出非零元素 { cout<<setw(8)<<bb[p].v; p=p+1; } else cout<<setw(8)<<0; //输出0 cout<<endl; } return; } //稀疏矩阵转置 template<class T> //函数模板,T为虚拟函数 X_Array<T> X_Array<T>::tran_X_Array() { X_Array<T> at; //定义转置矩阵对象 int k,p,q; at.mm=nn; //转置矩阵行、列数及非零元素个数 at.nn=mm; at.tt=tt; at.bb=new B<T> [tt]; //申请转置矩阵三列二维数组空间 k=0; for(p=0;p<nn;p++) //按排序扫描所有非零元素 for(q=0;q<tt;q++) { if(bb[q].j==p) //将非零元素信息依次存放到转置矩阵的三列二维数组中 { at.bb[k].i=bb[q].j; at.bb[k].j=bb[q].i; at.bb[k].v=bb[q].v; k=k+1; } } at.pos=new int [at.mm]; //申请POS向量空间 at.num=new int [at.mm]; //申请NUM向量空间 for(k=0;k<at.mm;k++) //NUM向量初始化 at.num[k]=0; for(k=0;k<at.tt;k++) //构造转置矩阵的NUM向量 at.num[at.bb[k].i]=at.num[at.bb[k].i]+1; at.pos[0]=0; for(k=1;k<at.mm;k++) //构造转置矩阵的POS向量 at.pos[k]=at.pos[k-1]+at.num[k-1]; return(at); //返回转置矩阵 } //稀疏矩阵相加 template<class T> //函数模板,T为虚拟函数 X_Array<T> X_Array<T>::operator + (X_Array<T> &b) { X_Array<T> c; //定义和矩阵对象 B<T> *a; T d; int m,n,k,p; if((mm!=b.mm)||(nn!=b.nn)) cout<<"不能相加!"<<endl; else { a=new B<T> [tt+b.tt]; //临时申请一个三列二维数组空间 p=0; for(k=0;k<mm;k++) //逐次处理 { m=pos[k]; n=b.pos[k]; while ((bb[m].i==k) && (b.bb[n].i==k))//行号相同 { if(bb[m].j==b.bb[n].j)//列号相同则相加 { d=bb[m].v+b.bb[n].v; if(d!=0) //相加后非零 { a[p].i=k; a[p].j=bb[m].j; a[p].v=d; p=p+1; } m=m+1; n=n+1; } else if(bb[m].j < b.bb[n].j)//列号不同则复制列号小的一项 { a[p].i=k; a[p].j=bb[m].j; a[p].v=bb[m].v; p=p+1; m=m+1; } else //列号不同复制另一项 { a[p].i=k; a[p].j=b.bb[n].j; a[p].v=b.bb[n].v; p=p+1; n=n+1; } } while (bb[m].i==k) //复制矩阵中本行剩余的非零元素 { a[p].i=k; a[p].j=bb[m].j; a[p].v=bb[m].v; p=p+1; m=m+1; } while (b.bb[n].i==k) //复制另一矩阵中本行剩余非零元素 { a[p].i=k; a[p].j=b.bb[n].j; a[p].v=b.bb[n].v; p=p+1; n=n+1; } } c.mm=mm; c.nn=nn; c.tt=p; c.bb=new B<T> [p]; //申请一个三列二维数组空间 for(k=0;k<p;k++) //复制临时三列二位数组空间中的元素 { c.bb[k].i = a[k].i; c.bb[k].j = a[k].j; c.bb[k].v = a[k].v; } delete [] a; //释放临时三列二维数组空间 c.pos=new int [c.mm]; //申请POS向量空间 c.num=new int [c.mm]; //申请NUM向量空间 for(k=0;k<c.mm;k++) //NUM向量初始化 c.num[k]=0; for(k=0;k<c.tt;k++) //构造NUM向量 c.num[c.bb[k].i] = c.num[c.bb[k].i]+1; c.pos[0]=0; for(k=1;k<c.mm;k++) //构造POS向量 c.pos[k]=c.pos[k-1]+c.num[k-1]; } return(c); //返回相加结果 } //系数矩阵相乘 template<class T> //函数模板,T为虚拟函数 X_Array<T> X_Array<T>::operator * (X_Array &b) { X_Array<T> cc; int k,m,n,p,t; T *c; //定义乘积矩阵 if(nn!=b.mm) cout<<"两矩阵无法相乘!"<<endl; else { c=new T[mm *b.mm]; //申请乘积矩阵的临时空间 k=0; for (m=0;m<mm;m++) for(n=0;n<b.nn;n++) { c[k]=0; //乘积矩阵元素清零 k=k+1; } for (m=0;m<tt;m++) //对于左矩阵中的每一个非零元素 { k=bb[m].j; //左矩阵中非零元素的列值k n=b.pos[k]; //右矩阵中行号与k相同的第一个非零元素的位置 t=b.pos[k]+b.num[k]; //右矩阵中行号与k相同的最后一个非零元素的位置 while (n!=t) { p=bb[m].i*b.nn+b.bb[n].j; //在乘积矩阵中的位置 c[p]=c[p]+bb[m].v*b.bb[n].v;//累加非零元素的乘积 n=n+1; } } cc.th_X_Array(mm,b.nn,c); //由一般稀疏矩阵转换成用三列二维数组表示 delete [] c; //释放乘积矩阵的临时空间 } return(cc); //返回用三列二维数组表示的乘积矩阵 } void main() { B<double>a[8]={{1,3,3.0},{1,8,1.0},{3,1,9.0},{4,5,7.0}, {5,7,6.0},{6,4,2.0},{6,6,3.0},{7,3,5.0}}; X_Array<double>x,y,z,xt,c; //定义稀疏矩阵类对象,矩阵元素为双精度型 x.cp_X_Array(7,8,8,a); //复制三元组数组生成稀疏矩阵类对象x cout<<"输出矩阵x:"<<endl; x.prt_X_Array(); xt=x.tran_X_Array(); //稀疏矩阵转置 cout<<"输出稀疏矩阵x的转置xt:"<<endl; xt.prt_X_Array(); y.in_X_Array(); //以三元组形式从键盘输入稀疏矩阵非零元素 cout<<"输出稀疏矩阵y:"<<endl; y.prt_X_Array(); z=x+y; //稀疏矩阵相加 cout<<"输出稀疏矩阵z=x+y:"<<endl; z.prt_X_Array(); c=x*xt; //稀疏矩阵相乘 cout<<"输出c=x*xt:"<<endl; c.prt_X_Array(); }

浙公网安备 33010602011771号