稀疏矩阵的相关操作(存储、转置、快速转置、相加)

题目要求:

稀疏矩阵的压缩存储
template<class T>
class SparseMatrix
{
    template<class T>
    struct Trituple
    {
        Trituple(size_t row, size_t col, const T& data)
            : _row(row)
            , _col(col)
            , _data(data)
        {}

        Trituple()
        {}

        size_t _row;
        size_t _col;
        T _data;
    };

public:

        // 稀疏矩阵的压缩存储
    SparseMatrix(int* array, size_t row, size_t col, const T& invalid)
        : _row(row)
        , _col(col)
        , _invalid(invalid)
    {
    }

    SparseMatrix()
    {}

        // 访问稀疏矩阵中row行col中的元素
    T& Access(int row, int col);

        // 还原稀疏矩阵
    template<class T>
    friend ostream& operator<<(ostream& _cout, SparseMatrix<T>& s);

    // 实现稀疏矩阵的逆置,并给出时间复杂度
    SparseMatrix<T> Transprot();

    // 实现稀疏矩阵的快速逆置,并给出时间复杂度
    SparseMatrix<T> FastTransprot()

        // 实现稀疏矩阵的加法操作
    SparseMatrix<T> operator+(const SparseMatrix<T>& sp);

private:
    vector<Trituple<T>> _sm;
    size_t _row;
    size_t _col;
    T _invalid;
};

代码实现:

#include<vector>

#include<iostream>
using namespace std;

//稀疏矩阵的基本操作
//值存储有效元素

template<class T>
class SparseMatrix
{
public:
    //构造
    SparseMatrix()
    {}
    SparseMatrix(int* 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<T>(i, j, array[i*col + j]));

                }
            }
        }
    }

    //转置 :行转化为列,列转化为行
    SparseMatrix<T> Transport()
    {
        SparseMatrix<T> sm;
        sm._row = _col;
        sm._col = _row;
        sm._invalid = _invalid;

        //时间复杂度:O(M*N)
        //注意:直接存储是有问题的。因为打印是按照行优先进行打印的,所以存储时应按照一行进行存储
        for (int i = 0; i < _col; ++i)
        {
            vector<Trituple<T>>::iterator it = _sm.begin();
            while (it != _sm.end())
            {
                if (i == it->_col)
                {
                    sm._sm.push_back(Trituple<T> (it->_col,it->_row,it->_data));
                }
                it++;

            }
        }
        return sm;

    }


    //访问
    T& Access(size_t row,size_t col)
    {
        //遍历数组两种方法
        //1.for循环
        //2.迭代器
        vector<Trituple<T>>::iterator it = _sm.begin();

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

    }

    //输出  ->友元输出
    template<class T>
    friend ostream& operator <<(ostream& _cout, const SparseMatrix<T>& s)
    {
        //直接调用是访问函数效率比较低
        //因为它是按照行优先进行存储的
        int index = 0;
        for (size_t i = 0; i < s._row; ++i)
        {
            for (size_t j = 0; j < s._col; ++j)
            {
                //注意遍历时,一定要注意越界问题
                if (index<s._sm.size()&&i == s._sm[index]._row&&j == s._sm[index]._col)
                {
                    _cout << s._sm[index++]._data << " ";
                }
                else
                {
                    cout << s._invalid << " ";
                }
            }
            _cout <<endl;
        }
        return _cout;

    }


    //快速转置

    //思想:用两个数组统计出,每一列元素的个数,同统计出转置时,
    //先开辟好空间,根据该行列所在的偏移位置,直接定位到三元组元素的位置
    SparseMatrix<T> FastTransport()
    {
        SparseMatrix<T> sm;
        sm._row = _col;
        sm._col = _row;
        sm._sm.resize(_sm.size());

        int * pRowCounts = new int[_col];//原矩阵每一列的元素个数
        int * pRowStart = new int[_col];//每一行的元素的起始位置(原矩阵每一列的起始位置)
        memset(pRowStart,0,sizeof(pRowStart[0])*_col);
        memset(pRowCounts, 0, sizeof(pRowCounts[0])*_col);



        for (size_t i = 0; i < _sm.size(); ++i)
        {
            pRowCounts[_sm[i]._col]++;
        }


        //每一行的元素的起始位置(原矩阵每一列的起始位置)

        for (size_t i = 1; i < _col; ++i)
        { 
            pRowStart[i] = pRowStart[i - 1] + pRowCounts[i-1];
        }


        //第三步:从原_sm中的元素直接定位到到对应位置

        for (size_t i = 0; i < _sm.size(); ++i)
        {
            int & addr = pRowStart[_sm[i]._col];
            sm._sm[addr] = Trituple<T>(_sm[i]._col,_sm[i]._row,_sm[i]._data);
            addr++;
        }


        return sm;
    }


    //加法
    //思想:将二位数组当成一维,然后对应的元素的位置进行比对,如果相同,进行相加
    SparseMatrix<T> operator + (const SparseMatrix<T>& s)
    {
        SparseMatrix<T> sm;
        sm._row = _row;
        sm._col = _col;

        if (s._col != _col || s._row != _row)
        {
            return sm;
        }

        int left = 0;
        int right = 0;
        int addr1 = 0; int addr2 = 0;

        /*if (_sm[left]._row == s._sm[right]._row&&_sm[left]._col == s._sm[right]._col)
        {
            sm.push_back(Trituple<T>(_sm[left]._row,_sm[left]._col,_sm[left]._data+s._sm[right]._col));
        }*/

        while (left < _sm.size() && right < s._sm.size())
        {

            addr1 = _sm[left]._row*_col + _sm[left]._col;
            addr2 = s._sm[right]._row*s._col + s._sm[right]._col;

            if (addr1 == addr2)
            {
                sm._sm.push_back(Trituple<T>(_sm[left]._row, _sm[left]._col, _sm[left]._data + s._sm[right]._data));
                ++left;
                ++right;
            }
            else if (addr1 < addr2)
            {
                sm._sm.push_back(Trituple<T>(_sm[left]._row, _sm[left]._col, _sm[left]._data));
                left++;
            }
            else
            {
                sm._sm.push_back(Trituple<T>(_sm[right]._row, _sm[right]._col, _sm[right]._data));
                right++;
            }
        }

        while (left < _sm.size())
        {
            sm._sm.push_back(Trituple<T>(_sm[left]._row, _sm[left]._col, _sm[left]._data));
            left++;
        }
        while (right < s._sm.size())
        {
            sm._sm.push_back(Trituple<T>(_sm[right]._row, _sm[right]._col, _sm[right]._data));
            right++;
        }
        return sm;
    }

    template<class T>
    struct Trituple
    {
        Trituple(size_t row, size_t col, size_t data)
        :_row(row)
        , _col(col)
        , _data(data)
        {
        }
        Trituple()
        {}

        size_t _row;
        size_t _col;
        T _data;
    };

private:
    vector<Trituple<T>> _sm;//三元组数组
    size_t _row;
    size_t _col;
    T _invalid;

};


void Test()
{
    int array[5][5] =
    { { 1, 0, 3, 0, 5 },
    { 0, 0, 0, 0, 0 },
    { 1, 0, 3, 0, 5 },
    { 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0 } };

    SparseMatrix<int> sm((int*)array,sizeof(array)/sizeof(array[0]),sizeof(array[0])/sizeof(array[0][0]),0);

    //cout<<sm.Access(2, 2)<<endl;
    cout << sm << endl;
    cout << endl;
    //转置
    /*SparseMatrix<int> rsm1 = sm.Transport();
    cout << rsm1 << endl << endl;*/

    SparseMatrix<int> rsm2 = sm.FastTransport();
    cout << rsm2 << endl;

    //快速转置
    //矩阵的加法
    SparseMatrix<int> rsm3 = sm + rsm2;
    cout << rsm3 << endl;


}

int main()
{
    Test();
    return 0;

}

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值