频道栏目
首页 > 程序开发 > 综合编程 > 其他综合 > 正文
稀疏矩阵及其逆置矩阵
2017-04-26 09:25:49           
收藏   我要投稿

稀疏矩阵及其逆置矩阵:在矩阵中,若数值为0的元素数目远远多于非0元素的数目时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。

M*N的矩阵,矩阵中有效值得个数远小于无效值的个数,且这些数据的分布没有规律。

【稀疏矩阵压缩存储】 压缩存储值存储极少数的有效数据。使用{row,col,value}三元组(Trituple)存储 每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放。

矩阵逆置
将原矩阵的行、列对换,也就是将[i][j]和[j][i]位置上的数据对换。

快速逆置

源代码如下:

#include
#include
#include 
using namespace std;

//实现稀疏矩阵的压缩存储、转置以及快速逆置、两个稀疏矩阵相加
template
class SparseMatrix
{
    template
    struct Trituple  //封装三元组
    {
        Trituple(int row = 0, int col = 0, const T& value= T())
            : _row(row)
            , _col(col)
            , _value(value)
        {}

        size_t _row;
        size_t _col;
        T _value;
    };

public:
    // 
    SparseMatrix(T* array, size_t row, size_t col, const T& invalid)
        :_row(row)
        ,_col(col)
        ,_invalid(invalid)
    {
        for(size_t i=0; i<_row; i++)
        {
            for(size_t j=0; j<_col; j++)
            {
                if(array[i*_col + j] != invalid)
                {
                    _sm.push_back(Trituple(i, j, array[i*_col  +j]));
                }
            }
        }
    }
    SparseMatrix()
    {}

    // 访问矩阵中的元素
    T& Access(int row, int col)
    {
        vector>::iterator it = _sm.begin();

        while(it != _sm.end())
        {
            if(it->_row == row && it->_col == col)
            {
                return it->_value;
            }
            ++it;
        }

        return _invalid;  //找不到存储的值就返回无效值
    }

    template
    friend ostream& operator<<(ostream& _cout, const SparseMatrix& sm)
    {
        size_t index = 0;
        for(size_t i=0; i Transport()
    {
        SparseMatrix temp;
        temp._row = _col;
        temp._col = _row;
        temp._invalid = _invalid;

        for(size_t i=0; i<_col; ++i)
        {
            size_t index =0 ;
            while(index<_sm.size())
            {
                Trituple &t = _sm[index];
                if(t._col == i)
                {
                    temp._sm.push_back(Trituple(t._col, t._row, t._value));  
                }
                index++;
            }
        }
        return temp;
    }

    // 稀疏矩阵的快速转置
    SparseMatrix FastTransport()
    {
        SparseMatrix temp;
        temp._col = _row;
        temp._row = _col;
        temp._invalid = _invalid;
        temp._sm.resize(_sm.size());

        //统计原矩阵中每一列有效个数
        int *pCount = new int[_col];
        memset(pCount, 0, _col*sizeof(int));

        vector>::iterator it = _sm.begin();
        while(it != _sm.end())
        {
            pCount[it->_col]++;
            ++it;
        }

        //原矩阵中每一列有效数据在新矩阵中的起始位置
        int *pAddr = new int[_col];
        memset(pAddr, 0, _col*sizeof(int));
        for(size_t i=1; i<_col; ++i)
        {
            pAddr[i] = pAddr[i-1] + pCount[i-1];
        }

        //放置元素
        it = _sm.begin();
        while(it != _sm.end())
        {
            temp._sm[pAddr[it->_col]] = Trituple(it->_col, it->_row, it->_value);
            pAddr[it->_col]++;
            ++it;
        }

        delete[] pCount;
        delete[] pAddr;

        return temp;
    }

    // 两个矩阵相加
    SparseMatrix operator+(const SparseMatrix& sp)
    {
        assert(_row == sp._row);
        assert(_col == sp._col);

        SparseMatrix sum;
        sum._row = _row;
        sum._col = _col;
        sum._invalid = _invalid;

        int idxL = 0;
        int idxR = 0;
        int leftAddr = 0;
        int rightAddr = 0;

        while(idxL < _sm.size() && idxR < sp._sm.size())
        {
            leftAddr = _sm[idxL]._row*_col + _sm[idxL]._col;
            rightAddr = sp._sm[idxR]._row*_col + sp._sm[idxR]._col;

            if(leftAddr < rightAddr)
            {
                sum._sm.push_back(_sm[idxL++]);
                continue;
            }
            else if(leftAddr > rightAddr)
            {
                sum._sm.push_back(sp._sm[idxR++]);
                continue;
            }
            else
            {
                T value = _sm[idxL]._value + sp._sm[idxR]._value;
                if(value != _invalid)
                {
                    sum._sm.push_back(Trituple(_sm[idxL]._row, _sm[idxL]._col, value));
                    idxL++;
                    idxR++;
                }
            }
        }
        if(!_sm.empty())
        {
            while(idxL < _sm.size())
            {
                sum._sm.push_back(_sm[idxL++]);
            }
            while(idxR < sp._sm.size())
            {
                sum._sm.push_back(sp._sm[idxR++]);
            }
        }
        return sum;
    }

private:
    vector> _sm;
    size_t _row;  //行数
    size_t _col;  //列数
    T _invalid;   //无效值
};

void FunTest()
{
    int array1 [6][5] = {
        {1, 0, 3, 0, 5},
        {0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0},
        {1, 0, 3, 0, 5},
        {0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0}};

    int array2 [6][5] = {
            {1, 0, 3, 0, 5},
            {0, 2, 0, 0, 0},
            {0, 0, 0, 0, 0},
            {1, 0, 3, 0, 5},
            {0, 0, 8, 0, 0},
            {0, 0, 0, 0, 1}};

    SparseMatrix sm((int*)array1, 6, 5, 0);
    SparseMatrix sm4((int*)array2, 6, 5, 0);
    /*cout< sm1;
    SparseMatrix sm2;
    sm1 = sm.Transport();
    sm1.PrintMatrix();

    sm2 = sm.FastTransport();
    sm2.PrintMatrix();*/

    sm4.PrintMatrix();
    cout< sm3;
    sm3 = sm+sm4;
    sm3.PrintMatrix();
}

int main()
{
    FunTest();

    system("pause");
    return 0;
}
点击复制链接 与好友分享!回本站首页
上一篇:回溯 子集问题
下一篇:最大似然估计
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站