您的位置:首页 > 其它

稀疏矩阵及其逆置矩阵

2017-04-25 22:43 465 查看
在矩阵中,若数值为0的元素数目远远多于非0元素的数目时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。

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



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

矩阵逆置

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



快速逆置



源代码如下:

#include<iostream>
#include<assert.h>
#include <vector>
using namespace std;

//实现稀疏矩阵的压缩存储、转置以及快速逆置、两个稀疏矩阵相加
template<class T>
class SparseMatrix
{
template<class T>
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<T>(i, j, array[i*_col  +j]));
}
}
}
}
SparseMatrix()
{}

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

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

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

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++)
{
if(index<sm._sm.size() && (sm._sm[index]._row == i)
&& (sm._sm[index]._col == j))
{
_cout<<sm._sm[index]._value<<" ";
index++;
}
else
{
_cout<<sm._invalid<<" ";
}
}
_cout<<endl;
}

return _cout;

}

void PrintMatrix()
{
for(size_t i=0; i<_row; ++i)
{
for(size_t j=0; j<_col; ++j)
{
cout<<Access(i, j)<<" ";
}
cout<<endl;
}
}

//给出两种逆置方法的时间复杂度
// 稀疏矩阵的转置
SparseMatrix<T> Transport()
{
SparseMatrix<T> 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> &t = _sm[index];
if(t._col == i)
{
temp._sm.push_back(Trituple<T>(t._col, t._row, t._value));
}
index++;
}
}
return temp;
}

// 稀疏矩阵的快速转置
SparseMatrix<T> FastTransport()
{
SparseMatrix<T> 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<Trituple<T>>::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<T>(it->_col, it->_row, it->_value);
pAddr[it->_col]++;
++it;
}

delete[] pCount;
delete[] pAddr;

return temp;
}

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

SparseMatrix<T> 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<T>(_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<Trituple<T>> _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<int> sm((int*)array1, 6, 5, 0);
SparseMatrix<int> sm4((int*)array2, 6, 5, 0);
/*cout<<sm.Access(0 ,3)<<endl;
cout<<sm.Access(3 ,2)<<endl;
cout<<sm.Access(3 ,0)<<endl;
cout<<sm.Access(2 ,4)<<endl;
cout<<sm.Access(3 ,4)<<endl;*/
cout<<sm<<endl;
sm.PrintMatrix();
cout<<endl;
/*SparseMatrix<int> sm1;
SparseMatrix<int> sm2;
sm1 = sm.Transport();
sm1.PrintMatrix();

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

sm4.PrintMatrix();
cout<<endl;

SparseMatrix<int> sm3;
sm3 = sm+sm4;
sm3.PrintMatrix();
}

int main()
{
FunTest();

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  稀疏矩阵 逆置