#include<iostream>
#include<vector>
#include<assert.h>
#include<string.h>
using namespace std;
template <typename T>
class SparseMatrix
{
public:
//构造
SparseMatrix()
{}
SparseMatrix(int* arr,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(arr[i*_col+j]!=_invalid)
{
_sm.push_back(Trituple<T>(i,j,arr[i*_col+j]));
}
}
}
}
//访问
//方法1:
/*T& Access(size_t row,size_t col)
{
for(size_t i=0;i<_sm.size();i++)
{
if(_sm[i]._row==row && _sm[i]._col==col)
return _sm[i]._data;
}
return _invalid;
}*/
//方法2:迭代器
T& Access(size_t row,size_t col)
{
//定义迭代器
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<typename T>
friend ostream& operator<<(ostream& _cout,SparseMatrix<T> sm)
{
//方法1:访问Access(),循环多,开销大
/*
for(size_t i=0;i<sm._row;i++)
{
for(size_t j=0;j<sm._col;j++)
{
_cout<<sm.Access(i,j)<<" ";
}
_cout<<endl;
}
*/
//方法2:
size_t index=0;
for(size_t i=0;i<sm._row;i++)
{
for(size_t j=0;j<sm._col;j++)
{
//index会越界,所以需要判断
if(index<sm._sm.size() && sm._sm[index]._row==i && sm._sm[index]._col==j)
_cout<<sm._sm[index++]._data<<" ";
else
_cout<<sm._invalid<<" ";
}
_cout<<endl;
}
return _cout;
}
//逆置
SparseMatrix<T> Transport()
{
SparseMatrix<T> sm;
sm._row=_col;
sm._col=_row;
sm._invalid=_invalid;
//有问题:不符合“以行优先存储”的规定,打印出来有问题
/*for(size_t i=0;i<_sm.size();i++)
{
sm._sm.push_back(Trituple<T>(_sm[i]._col,_sm[i]._row,_sm[i]._data));
}*/
for(size_t 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>(i,it->_row,it->_data));
++it;
}
}
return sm;
}
//快速逆置
SparseMatrix<T> FastTransport()
{
SparseMatrix<T> sm;
sm._row=_col;
sm._col=_row;
sm._invalid=_invalid;
//开辟新空间
sm._sm.resize(_sm.size());
//统计每列的有效值个数
int* pCount=new int[_col];
memset(pCount,0,_col*sizeof(pCount[0]));//清零
for(size_t i=0;i<_sm.size();i++)
{
pCount[_sm[i]._col]++;
}
//原矩阵的每列(即转置后的每行)在新矩阵的其实位置
int* pAddr=new int[_col];
memset(pAddr,0,_col*sizeof(pAddr[0]));
for(size_t i=1;i<_sm.size();i++)
{
pAddr[i]=pAddr[i-1]+pCount[i-1];
}
//放元素到新空间
for(size_t i=0;i<_sm.size();i++)
{
int& addr=pAddr[_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>& sm)
{
assert(_row==sm._row && _col==sm._col);
SparseMatrix<T> ret;
ret._col=_col;
ret._row=_row;
ret._invalid=_invalid;
int LeftAddr=0;
int RightAddr=0;
int Lidex=0;
int Ridex=0;
while(Lidex<_sm.size() && Ridex<sm._sm.size())
{
LeftAddr=_sm[Lidex]._row*_col+_sm[Lidex]._col;
RightAddr=sm._sm[Ridex]._row*_col+sm._sm[Ridex]._col;
if(LeftAddr <RightAddr)
{
ret._sm.push_back(_sm[Lidex]);
Lidex++;
}
else if(LeftAddr >RightAddr)
{
ret._sm.push_back(sm._sm[Ridex]);
Ridex++;
}
else
{
Trituple<T> temp(_sm[Lidex]);
temp._data+=sm._sm[Ridex]._data;
if(temp._data!= _invalid)
ret._sm.push_back(temp);
Lidex++;
Ridex++;
}
}
while(Lidex <_sm.size())
{
ret._sm.push_back(_sm[Lidex++]);
}
while(Ridex <sm._sm.size())
{
ret._sm.push_back(sm._sm[Ridex++]);
}
return ret;
}
private:
//三元组存储
template <typename 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;
};
private:
size_t _row;
size_t _col;
T _invalid;//无效值
vector<Trituple<T>> _sm;
};
int main()
{
int arr[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 arr1[6][5]={{0,0,3,0,5},
{0,0,0,0,0},
{0,0,0,0,0},
{1,0,3,0,5},
{0,0,0,1,0},
{0,0,0,0,0},};
SparseMatrix<int> sm((int*)arr,sizeof(arr)/sizeof(arr[0]),sizeof(arr[0])/sizeof(arr[0][0]),0);
SparseMatrix<int> sm1((int*)arr1,sizeof(arr1)/sizeof(arr1[0]),sizeof(arr1[0])/sizeof(arr1[0][0]),0);
//cout<<sm.Access(3,2)<<endl;
cout<<sm<<endl;
cout<<sm1<<endl;
cout<<sm+sm1<<endl;
//cout<<sm.Transport()<<endl;
//cout<<sm.FastTransport()<<endl;
return 0;
}
稀疏矩阵的基本操作
最新推荐文章于 2023-04-13 14:37:11 发布