用三列二维数组表示的稀疏矩阵类

来源:互联网 发布:java短信接口开发实例 编辑:程序博客网 时间:2024/06/10 02:32

1.稀疏矩阵:矩阵中绝大多数的元素值为零,只有少数的非零元素值;

2.对稀疏矩阵采用压缩存储的目的是为了节省存储空间,并且,稀疏矩阵压缩存储后,还要能够比较方便地访问其中的没个元素(包括零元素和非零元素);

3.对稀疏矩阵进行压缩存储有两种方法:稀疏矩阵的三列二维数组表示和十字链表方法。

稀疏矩阵的三列二维数组表示:

    (1)每个非零元素用三元组表示:(i,j,v)分别对应(行,列,非零元素);

    (2) 为了表示唯一性,除了每个非零元素用一个三元组表示外,在所有的非零元素三元组之前添加一组信息(I,J,V)对应(总行数,总列数,非零元素个数),也就是说,我们要确定确切的稀疏矩阵,必须先知道该稀疏矩阵的总行数,总列数,非零个数;

    (3)为了便于在三列二维数组B中访问稀疏矩阵A中的各元素,通常还附设两个长度与稀疏矩阵A的行数相同的向量POS与NUM。其中POS[K]表示稀疏矩阵A中的第k行的第一个非零元素(如果有的话)在三列二维组B中的行号;NUM[k]表示稀疏矩阵A中第k行中非零元素的个数;

pos[0]=0; pos[k]=pos[k-1]+num[k-1]

4.三列二维数组表示的稀疏矩阵类如下:

文件名:X_Array.h

#include <iostream>#include <iomanip>using namespace std;template <class T>struct B{int i;   //非零元素所在行号int j;   //非零元素所在列号T v;     //非零元素值};//三列二维数组表示的稀疏矩阵类template <class 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>void X_Array<T>::in_X_Array(){int k,m,n;cout<<"输入行数 列数 非零元素个数:"<<endl;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];num=new int[mm];for(k=0;k<mm;k++)  //num向量初始化num[k]=0;      //初始化mm行的每行num都设为零for(k=0;k<tt;k++)num[bb[k].i]=num[bb[k].i]+1;  //提取每个非零元素的行号,出现行号的数组num值加1,当n个非零元素在同一行时,则加n次。pos[0]=0;for(k=1;k<mm;k++)       //构造pos向量pos[k]=pos[k-1]+num[k-1];  //pos[k]表示在稀疏矩阵第k行中第一个非零元素在数组B中的行号return;}//复制三元数组template <class 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<tt;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];num=new int[mm];for(k=0;k<mm;k++)  //num向量初始化num[k]=0;      //初始化mm行的每行num都设为零for(k=0;k<tt;k++)num[bb[k].i]=num[bb[k].i]+1;  //提取每个非零元素的行号,出现行号的数组num值加1,当n个非零元素在同一行时,则加n次。pos[0]=0;for(k=1;k<mm;k++)       //构造pos向量pos[k]=pos[k-1]+num[k-1];  //pos[k]表示在稀疏矩阵第k行中第一个非零元素在数组B中的行号return;}// 由一般稀疏矩阵转换template <class 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++;  mm=m;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];num=new int[mm];for(k=0;k<mm;k++)  //num向量初始化num[k]=0;      //初始化mm行的每行num都设为零for(k=0;k<tt;k++)num[bb[k].i]=num[bb[k].i]+1;  //提取每个非零元素的行号,出现行号的数组num值加1,当n个非零元素在同一行时,则加n次。pos[0]=0;for(k=1;k<mm;k++)       //构造pos向量pos[k]=pos[k-1]+num[k-1];  //pos[k]表示在稀疏矩阵第k行中第一个非零元素在数组B中的行号return;}// 按行输出稀疏矩阵template <class 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;}elsecout<<setw(8)<<0;cout<<endl;}return;}// 稀疏矩阵转置template <class 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++;}}at.pos=new int[at.mm];at.num=new int[at.mm];for(k=0;k<at.mm;k++)at.num[k]=0;for(k=0;k<at.tt;k++)at.num[at.bb[k].i]=at.num[at.bb[k].i]+1;at.pos[0]=0;for(k=1;k<at.mm;k++)at.pos[k]=at.pos[k-1]+at.num[k-1];return (at);                                      //返回转置矩阵}// 稀疏矩阵相加template <class 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[m].j;a[p].v=b.bb[m].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[m].j;a[p].v=b.bb[m].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];c.num=new int[c.mm];for(k=0;k<c.mm;k++)c.num[k]=0;for(k=0;k<c.tt;k++)c.num[c.bb[k].i]=c.num[c.bb[k].i]+1;c.pos[0]=0;for(k=1;k<c.mm;k++)c.pos[k]=c.pos[k-1]+c.num[k-1];}return c;}template <class T>X_Array<T> X_Array<T>::operator* (X_Array<T> &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.nn];  //申请乘积矩阵的临时空间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;        //左矩阵中非零元素的列值Kn=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;}



2.实例应用:

#include "test2.h"#include<stdlib.h>int 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);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*y"<<endl;c.prt_X_Array();system("pause");return 0;}


3.实验结果:

 

 

原创粉丝点击