稀疏矩阵压缩存储
压缩存储值存储极少数的有效数据。使用{row,col,value}三元组(Trituple)存储
每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放。
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;
template <class T>
class SparseMatrix
{
struct Trituple //三元组
{
Trituple()
{}
Trituple(const T& data, size_t row, size_t col)
:_data(data)
, _row(row)
, _col(col)
{}
T _data;
size_t _row;
size_t _col;
};
public:
SparseMatrix()
{}
SparseMatrix(const T* Ma, 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)
{
Trituple tmp(Ma[i*col + j], i, j);
if (Ma[i*col + j] != invalid)
{
_v.push_back(tmp);
}
}
}
T& Access(const size_t n, const size_t m) //访问元素
{
assert(n < _row&&m < _col);
for (size_t i = 0; i < _v.size(); ++i)
if (_v[i]._row == n&&_v[i]._col == m)
return _v[i]._data;
return _invalid;
}
/*void show()
{
for (size_t i = 0; i < _row; ++i)
{
for (size_t i = 0; i < _col; ++j)
{
cout << Access(i, j) << " ";
}
cout << endl;
}
}*/
SparseMatrix Tranform() // 普通转置
{
SparseMatrix temp;
temp._row = _col;
temp._col = _row;
temp._invalid = _invalid;
for (size_t i = 0; i < _row; ++i)
{
for (size_t j = 0; j < _v.size(); ++j) //找出每一列的元素放入转置每一行
{
Trituple tmp(_v[j]._data, i, _v[j]._row);
if (_v[j]._col == i)
{
temp._v.push_back(tmp);
}
}
}
return temp;
}
template <class T>
friend ostream& operator<<(ostream& _cout, const SparseMatrix<T>& sm) //输出运算符重载
{
size_t index = 0;
for (size_t i = 0; i < sm._row; ++i)
{
for (size_t j = 0; j < sm._col; ++j)
{
Trituple tmp = sm._v[index];
if (tmp._row == i && tmp._col == j)
{
_cout << tmp._data << " ";
if (index < sm._v.size() - 1)
index++;
}
else
{
_cout << sm._invalid << " ";
}
}
cout << endl;
}
return _cout;
}
SparseMatrix FastTranform() // 快速转置
{
SparseMatrix temp;
temp._row = _col;
temp._col = _row;
temp._invalid = _invalid;
vector<int> RowCount;
vector<int> Addr;
temp._v.resize(_v.size());
RowCount.resize(_row);
Addr.resize(_col);
for (size_t i = 0; i < _v.size(); ++i)
{
RowCount[_v[i]._col]++; //转置后每行个数
}
Addr[0] = 0;
for (size_t i = 1; i < _col; i++)
{
Addr[i] = Addr[i - 1] + RowCount[i - 1]; //转置后每行偏移地址
}
for (size_t i = 0; i < _v.size(); i++) // 将元素放入对应地址的位置
{
size_t addr = Addr[_v[i]._col];
temp._v[addr]._data = _v[i]._data;
temp._v[addr]._row = _v[i]._col;
temp._v[addr]._col = _v[i]._row;
Addr[_v[i]._col]++; //对应行的下一个元素
}
return temp;
}
SparseMatrix operator+(const SparseMatrix<T>& sm) //加法运算符重载
{
assert(sm._row == _row || sm._col == _col);
SparseMatrix temp;
temp._row = _row;
temp._col = _col;
temp._invalid = _invalid;
size_t left = 0;
size_t right = 0;
while (left < _v.size() && right < sm._v.size())
{
int AddL = _v[left]._row*_col + _v[left]._col; //左操作原矩阵的相对于首元素偏移量
int AddR = sm._v[right]._row*_col + sm._v[right]._col; //右操作原矩阵的相对于首元素偏移量
if (AddL < AddR)
{
temp._v.push_back(_v[left]);
left++;
}
else if (AddL > AddR)
{
temp._v.push_back(sm._v[right]);
right++;
}
else
{
Trituple tmp;
tmp._data = _v[left]._data + sm._v[right]._data;
tmp._row = _v[left]._row;
tmp._col = _v[left]._col;
if (tmp._data != _invalid)
temp._v.push_back(tmp);
left++;
right++;
}
}
while (left < _v.size()) //左操作稀疏矩阵未访问完
{
temp._v.push_back(_v[left]);
left++;
}
while (right < sm._v.size()) //右操作稀疏矩阵未访问完
{
temp._v.push_back(sm._v[right]);
right++;
}
return temp;
}
private:
vector<Trituple> _v; //存放三元组
size_t _row; //行
size_t _col; //列
T _invalid; //无效值
};
int main()
{
int array[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 array1[6][5] = {
{ 1, 0, 3, 0, 5 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, -3, 0, 5 },
{ 1, 2, 0, 0, 0 },
{ 0, 0, 0, 0, 0 } };
SparseMatrix<int> SM( (int*)array, 6, 5, 0);
SparseMatrix<int> SM1((int*)array1, 6, 5, 0);
SparseMatrix<int> ret;
cout << SM.Access(3, 2) << endl;
/*ret = SM.Tranform();*/
/*ret = SM.FastTranform();*/
cout<<SM<<endl;
cout << SM1 << endl;
ret = SM + SM1;
cout << ret << endl;
return 0;
}