对称矩阵:N*N方阵A,特点Aij=Aji,对角线分割为上三角和下三角,压缩存储只需存储下三角数据。
稀疏矩阵:矩阵中有效数据很少,在存储时只存储有效数据,非法数据不存,在实现中创建一个结构体表示一个有效数据,并以行优先级先后顺序依次存放,并对稀疏矩阵实现转置和快速转置。
代码实现:
#include <iostream>
#include <cstdlib>
#include <assert.h>
#include <vector>
using namespace std;
template <class T>
class SymmetricMatrix //对称矩阵
{
public:
SymmetricMatrix(T* a,size_t n)
:_a(new T[n*(n+1)/2])
,_n(n)
{
size_t index=0;
for(size_t i=0;i<n;++i)
{
for(size_t j=0;j<n;++j)
{
if(i>=j)
{
_a[index++]=a[i*n+j];
}
else
{
break;
}
}
}
}
SymmetricMatrix()
:_a(0)
,_n(0)
{}
T& Access(size_t i,size_t j)
{
if(i>=j)
{
return _a[i*(i+1)/2+j];
}
else
{
return _a[j*(j+1)/2+i];
}
}
void Display() //打印矩阵
{
for(size_t i=0;i<_n;++i)
{
for(size_t j=0;j<_n;++j)
{
cout<<Access(i,j)<<" ";
}
cout<<endl;
}
cout<<endl;
}
protected:
T* _a;
size_t _n;
};
template <class T>
struct Triple //三元组结构体
{
Triple(const T& value=T(),size_t row=0,size_t col=0)
:_value(value)
,_row(row)
,_col(col)
{}
T _value;
size_t _row;
size_t _col;
};
template <class T>
class SparseMatrix //稀疏矩阵
{
public:
SparseMatrix(T* a,size_t m,size_t n,const T& invalid=T())
:_rowSize(m)
,_colSize(n)
,_invalid(invalid)
{
for(size_t i=0;i<m;++i)
{
for(size_t j=0;j<n;++j)
{
if(a[i*n+j]!=invalid)
{
_a.push_back(Triple<T>(a[i*n+j],i,j));
}
}
}
}
SparseMatrix()
:_rowSize(0)
,_colSize(0)
,_invalid(T())
{}
void Display() //打印矩阵
{
size_t index=0;
for(size_t i=0;i<_rowSize;++i)
{
for(size_t j=0;j<_colSize;++j)
{
if(index<_a.size()&&_a[index]._row==i&&_a[index]._col==j)
{
cout<<_a[index]._value<<" ";
++index;
}
else
{
cout<<_invalid<<" ";
}
}
cout<<endl;
}
cout<<endl;
}
SparseMatrix<T> Transport() //转置
{
SparseMatrix<T> tmp;
tmp._rowSize=_colSize;
tmp._colSize=_rowSize;
tmp._invalid=_invalid;
for(size_t i=0;i<_colSize;++i)
{
size_t index=0;
while(index!=_a.size())
{
if(_a[index]._col==i)
{
tmp._a.push_back(Triple<T>(_a[index]._value,_a[index]._col,_a[index]._row));
}
++index;
}
}
return tmp;
}
SparseMatrix<T> FastTransport() //快速转置
{
SparseMatrix<T> tmp;
tmp._rowSize=_colSize;
tmp._colSize=_rowSize;
tmp._invalid=_invalid;
//计算转置后每一行有效元素的个数
int* Count=new int[_colSize];
memset(Count,0,sizeof(int)*_colSize);
size_t index=0;
while(index!=_a.size())
{
Count[_a[index]._col]++;
++index;
}
//计算每一行第一个有效元素在新三元组中的下标
int* Start=new int[_colSize];
memset(Start,0,sizeof(int)*_colSize);
Start[0]=0;
for(size_t i=1;i<_colSize;++i)
{
Start[i]=Start[i-1]+Count[i-1];
}
/*根据旧三元组每一个有效数据的列数与上第一个有效元素在新三元组的下标得出
每一个有效数据的位置*/
index=0;
tmp._a.resize(_a.size());
while(index<_a.size())
{
tmp._a[Start[_a[index]._col]++]=Triple<T>(_a[index]._value,_a[index]._col,_a[index]._row);
++index;
}
return tmp;
}
protected:
vector<Triple<T>> _a;
size_t _rowSize;
size_t _colSize;
T _invalid;
};
void TestSparseMatrix()
{
int arr[6][5] = {{1, 0, 3, 0, 5},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{2, 0, 4, 0, 6},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}};
SparseMatrix<int> s((int*)arr,6,5,0);
s.Display();
//SparseMatrix<int> ret1=s.Transport();
//ret1.Display();
SparseMatrix<int> ret2=s.FastTransport();
ret2.Display();
}
void TestMatrix()
{
int a [5][5]={{0,1,2,3,4},
{1,0,1,2,3},
{2,1,0,1,2},
{3,2,1,0,1},
{4,3,2,1,0}};
SymmetricMatrix<int> s((int*)a,5);
s.Display();
}
int main()
{
TestMatrix();
TestSparseMatrix();
system("pause");
return 0;
}