数据结构-稀疏矩阵
使用一个三元组<row,column,value>来唯一的确定一个矩阵元素。
稀疏矩阵用一个三元组数组(三元组表)来表示。在该数组中,各矩阵元素的三元组按照在原矩阵中的位置,以行优先的顺序依次存放。
定义一个Trituple结构和一个SparseMatrix类,后者包括了Trituple结构数组、Rows、Cols、Terms、maxTerms(都是从0开始)。
求转置矩阵:
(1)创建一个新的SparseMatrix类对象b,构建存放指针CurrentB。
(2)在三元组数组中搜索列号为1的三元组(按数组顺序从前往后搜,搜出来肯定是按照行号从小到大的顺序),以新行号=1、新列号=旧行号,依次存放到b的三元组数组中。搜索Terms次。
(3)继续搜索旧列号为2、3、4......的三元组,循环Cols次。
if语句一共执行次数为O(Cols*Terms)
快速求转置矩阵:
(1)创建一个新的SparseMatrix类对象b。
(2)构建辅助数组rowSize[],统计转置前各列非0元素个数(转置后各行非0元素个数);构建辅助数组rowStart[],统计转置后每行第一个非0元素存放位置。
(3)遍历旧三元组数组,统计各列元素个数,为rowSize[]赋值。
通过关系rowStart[0]=0、rowStart[i]=rowStart[i-1]+rowSize[i-1](i>0)为rowStart[]赋值。
(4)遍历三元组数组,把每一个三元组依次加入到新三元组数组中,每添加一个三元组,对应位置rowStart[smArray[i].col]++
(5)把辅助数组delete释放空间。
此程序总共四个并列循环,时间复杂度分别为O(Cols)、O(Terms)、O(Cols)、O(Terms),则总时间复杂度为O(Cols+Terms)。
当Terms与Rows×Cols等数量级时,总时间复杂度为O(Cols+Terms)=O(Rows×Cols);当Terms远小于Rows×Cols时,则更加节约时间。
但程序需要增加两个大小为Cols的辅助数组。
#include <iostream> #include <stdlib.h>
using namespace std; const int DefaultSize=100; template <class T> struct Trituple{ //三元数组类定义 int row,col; //非零元素行号、列号 T value; Trituple<T>& operator=(Trituple<T>& x){row=x.row;col=x.col;value=x.value;} //结点赋值 } template <class T> class SparseMatrix{ //稀疏矩阵的类声明 friend ostream& operator<<(ostream& out,SparseMatrix<T>& M); friend istream& operator>>(istream& in,SparseMatrix<T>& M); public: SparseMatrix(int maxSz=DefaultSize); SparseMatrix(SparseMatrix<T> x); ~SparseMatrix(){delete []smArray;} SparseMatrix<T>& operator=(SparseMatrix<T>& x); SparseMatrix<T> Add(SparseMatrix<T>& b); SparseMatrix<T> Multiply(SparseMatrix<T>& b); SparseMatrix<T> Transpose(); SparseMatrix<T> FastTranspose(); private: int Rows,Cols,Terms; Trituple<T> *smArray; int maxTerms; } template <class T> SparseMatrix<T>::SparseMatrix(int maxSz):maxTerms(maxSz){ //构造函数 if(maxSz<1){ cerr<<"矩阵初始化值错误!"<<endl; exit(1); } smArray=new Trituple<T>[maxSz]; if(smArray=NULL){ cerr<<"存储分配错!"<<endl; exit(1); } Rows=Cols=Terms=0; } template <class T> SparseMatrix<T>::SparseMatrix(SparseMatrix<T>& x){ //复制构造函数 Rows=x.Rows; Cols=x.Cols; Terms=x.Terms; maxTerms=x.maxTerms; smArray=new Trituple<T>[maxTerms]; if(smArray==NULL){ cerr<<"分配存储错!"<<endl; exit(1); } for(int i=0;i<Terms;i++)smArray[i]=x.smArray[i]; } template <class T> ostream& operator<<(ostream& out, SparseMatrix<T>& M){ out<<"rows="<<M.Rows<<endl; out<<"cols="<<M.Cols<<endl; out<<"Nonzero terms="<<M.Terms<<endl; for (int i = 0; i<M.terms; i++) out<<"M["<<M.smArray[i].row<<"]["<< M.smArray[i].col<<"]="<<M.smArray[i].value<<endl; return out; } template <class T> istream& operator>>(istream& in, SparseMatrix<T>& M){ cout<<"Enter number or rows,columns,and terms"<<endl; in>>M.Rows>>M.Cols>>M.Terms; if (M.Terms>maxTerms){ cerr<<"Number of terms overflow!"<<endl; exit(1); } for (int i=0; i<M.Terms; i++){ cout<<"Enter row,column,and value of term:"<<i+1<<endl; in>>M.smArray[i].row>>M.smArray[i].col>>M.smArray[i].value; } return in; } template <class T> SpareMatrix<T> SparseMatrix<T>::Transpose(){ SparseMatrix<T> b(maxTerms); b.Rows = Cols; b.Cols = Rows; b.Terms = Terms; if (Terms > 0){ int CurrentB = 0; //存放指针 for (int k=0; k<Cols; k++) //按照列号(新行号)进行扫描,扫描Cols次 for (int i=0; i<Terms; i++) //在数组中找列号为k的三元组,if语句一共执行次数为O(Cols*Terms) if (sumArray[i].col==k){ b.smArray[CurrentB].row=k; b.smArray[CurrentB].col=smArray[i].row; b.smArray[CurrentB].value=smArray[i].value; CurrentB++; } } return b; } template <class T> SparseMatrix<T> SparseMatrix<T>::FastTranspose(){ // 程序总时间复杂度为O(Cols+Terms)=O(Cols*Rows),但增加了两个辅助数组 int *rowSize=new int[Cols]; //辅助数组,统计各列非零元素个数 int *rowStart=new int[Cols]; //辅助数组,预计转置后各行存放位置 SparseMatrix<T> b(maxTerms); //存放转置结果 b.Rows=Cols; b.Cols=Rows; b.Terms=Terms; if(Terms>0){ int i,j; for(i=0; i<Cols; i++) rowSize[i]=0; for(i=0; i<Terms; i++) rowSize[smArray[i].col]++; rowStart[0]=0; for(i=1; i<Cols; i++) rowStart[i]=rowStart[i-1]+rowSize[i-1]; for(i=0; i<Terms; i++){ j=rowStart[smArray[i].col]; b.smArray[j].row=smArray[i].col; b.smArray[j].col=smArray[i].row; b.smArray[j].value=smArray[i].value; rowStart[smArray[i].col]++; //每次加入一个元素后,对应行的rowStart加1 } } delete []rowStart; delete []rowStart; return b; }