稀疏矩阵

稀疏矩阵:一个m*n的矩阵,如果大多数元素都是0,则称为稀疏矩阵,一般规定稀疏矩阵的非0元素个数要小于n^2/3,有时还有小于n^2/5.

下面来实现一个稀疏矩阵的实例:
稀疏矩阵实现的思想是把无规则稀疏矩阵的非0元素映射到一个线性表中。为了重建矩阵结构,必须记录每个非0元素的行号和列号,因此数组元素需要三个域:row,col和value。为此定义结构maxtrixTerm。

template<class T>
struct matrixTerm
{
    int row;
    int col;
    T value;
};

下面仅写类matrixTerm的部分定义:

template<class T>
class sparseMatrix
{
    public:
    void transpose(sparseMatrix<T> &b);
    void add(sparseMatrix<T> &b,sparseMatrix<T>& c);
    private:
    int rows,cols;
    arrayList<matrixTerm<T>> terms;
}
template<class T>
ostream& operator<<(ostream& out,sparseMatrix<T>& x)
{
    out<<"rows="<<x.rows<<"columns="<<x.cols<<endl;
    out<<"nonozero terms="<<x.terms.size()<<endl;

    for(arrayList<matrixTerm<T>>::iterator i=x.terms.begin();
          i!=x.terms.end();i++)
          out<<"a("<<(*i).row<<','<<(*i).col<<")="<<(*i).value<<endl;

    return out;
}

以上是输出函数,是个友元函数,但我并没有在里面进行声明,因为懒。

template<class T>
istream& operator>>(istream& in,sparseMatrix<T>& x)
{
    int numberOfTerms;
    cout<<"Enter number of rows,columns,and #terms"<<endl;
    in>>x.rows>>x.cols>>numberOfTerms;
    if(x.rows<1||x.cols<1||numberOfTerms<x.rows*x.cols)
        throw illegalParameter();
    x.terms.reSet(numberOfTerms);
    matrixTerm<T>mTerm;
    for(int i=0;i<numberOfTerms;i++)
    {
        cout<<"Enter row.columns,and value of term"<<(i+1)<<endl;
        in>>mTerm.row>>mTerm.col>>merm.value;
        if(x.rows<1||x.cols<1)
        throw illegalParameter();
        x.terms.set(i,mTerm);
    }
    return in;
}

输入采取的是行主模式输入,即先输入第一行,再输入第二行,再输入第三行……。

template<class T>
void sparseMatrix<T>::transpose(sparseMatrix<T> &b)
{
    b.cols=rows;
    b.rows=cols;
    b.terms.reSet(terms.size());

    int* colSize=new int[cols+1];
    int* rowNext=new int[cols+1];

    for (int i=1;i<=cols;i++)]
    colSize[i]=0;
    for(arrayList<matrixTerm<T>>::iterator i=term.begin();
        i!=terms.end();i++)
        colSize[(*i).col]++;//colSize用来记录原矩阵每列的非零个数,比如colSize[i]代表i列的非零元素个数

    rowNext[1]=0;//转置矩阵第一行非零元素出现在b中第一个位子。其实第一行并没有非零元素,我们将其设置为0并不影响。
    for(int i=2;i<=cols;i++)//转置矩阵中第一行的第一个非零元素一定在b中第一个。
        rowNext[i]=rowNext[i-1]+colSize[i-1];//转置矩阵第二行的第一个非零元素在b中的位置
                                             //等于第一行的第一个非零元素加上第一行
                                             //的非零元素个数。
    matrixTerm<T> mTerm;
    for (arrayList<matrixTerm<T>>::iterator i=terms.begin();
         i!=terms.end();i++)
         {
            int j=rowNext[(*i).col]++; //b中的位置,第一个col将出现在行中的首元素,注意这是后++,下一个同列将出现在它后面。
            mTerm.row=rowNext[(*i).col]++;
            mTerm.col=(*i).row;
            mTerm.value=(*i).value;
            b.terms.set(j,mTerm);
         }
}

rowNext[i]里面装的是转置矩阵第i行首个非零元素在b数组里面的位置。

template<class T>
void sparseMatrix<T>::add(sparseMatrix<T> &b,sparseMatrix<T> &c)
{
    if(rows!=b.rows||cols!=b.cols)
        throw matrixSizeMismatch();
    c.rows=rows;
    c.cols=cols;
    c.terms.clear;
    int cSize=0;

    arrayList<matrixTerm<T>>::iterator it=terms.begin();
    arrayList<matrixTerm<T>>::iterator ib=b.terms.begin();
    arrayList<matrixTerm<T>>::iterator itEnd=terms.end();
    arrayList<matrixTerm<T>>::iterator ibEnd=b.terms.end();

    while(it!=itEnd&&ib!=ibEnd)
    {
        int tIndex=(*it).row*cols+(*it).col;//列数乘以当前行数+当且列数等于当前位置,通过这个进行比较再适合不过了。
        int bIndex=(*ib).row*cols+(*ib).col;
        if(tIndex<bIndex)
        {
            c.terms.insert(cSize++,*it);
            it++;
        }
        else 
        {
            if(tIndex==bIndex)
            {
                if((*it).value+(*ib).value!=0)
                {
                    matrixTerm<T>mTerm;
                    mTerm.row=(*it).row;
                    mTerm.col=(*it).col;
                    mTerm.value=(*it).value+(*ib).value;
                    c.terms.insert(cSize++,mTerm);
                }
                it++;
                ib++;
            }
            else
        {
            c.terms.insert(cSize++,*ib);
            ib++
        }

        }

    }
    for(;it!=itEnd;ib++)
        c.terms.insert(cSize++,*it);
    for(;ib!=ibEnd;ib++)
        c.terms.insert(cSize++,*ib);
}

从头开始循环,只有当两个元素的位置相同时才进行相加,否则将在前的那个元素直接放到c数组里面,然后将其迭代器加一,再次进行比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值