稀疏矩阵的基本操作

#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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值