稀疏矩阵类(以三列二维数组表示)

这是一个用三列二维数组表示的稀疏矩阵类。

这里将类与主函数放在一起以便于阅读,如有其他需要请自行封装。

运行结果及源码在下方给出。

注:蓝色下划线需要通过键盘键入

 

 

//稀疏矩阵类(以三列二维数组表示)
#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();
}

 

posted @ 2020-03-30 18:40  曲杨  阅读(395)  评论(0)    收藏  举报