稀疏矩阵的基本操作

来源:互联网 发布:火锅烧烤网络营销策划 编辑:程序博客网 时间:2024/05/16 15:48

#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;}


0 0
原创粉丝点击