c++ 数据结构 稀疏矩阵类的定义及其各种操作的实现

稀疏矩阵类:

     该类型的矩阵中0元素占多半,我们平常储存一般矩阵一般用二维数组,但是该矩阵的0元素既占用存储空间,而且在运算中会花费大量时间来进行0元素的无效运算。

因此我们利用三元数组(注意不是三维数组)存储非零元素的坐标和值。

以下是稀疏矩阵的类定义和各种操作的实现代码:

1.自定义数据类型:包含下标和值,及赋值运算符

# include<iostream>
using namespace std;
struct Trituple{        //自定义数据结构:矩阵元素的行,列,值;
	int row,col;
	int value;
	Trituple& operator=(Trituple& x){  //赋值运算符重载
		row=x.row;
		col=x.col;
		value=x.value;
		return *this;
	}
};

2.稀疏矩阵类:

# include"Trituple.h"
# include<iostream>
# include<assert.h>
using namespace std;
const int DefaultSize=100;
class SparseMatrix{    //稀疏矩阵
private:
	int Rows,Cols,Terms;   //行数,列数,非零元素的个数
	Trituple *smArray;   //存非零元素的三元数组
	int maxTerms;    //三元组最大可容纳的元素个数
public:
	SparseMatrix(int maxSz=DefaultSize);  //构造函数
	SparseMatrix(SparseMatrix& SM);      //赋值构造函数
	~SparseMatrix(); //析构函数
	SparseMatrix& operator=(SparseMatrix& SM); //赋值运算符重载
	SparseMatrix Transpose();     //矩阵转置
	SparseMatrix Add(SparseMatrix& b);      //矩阵的加法
	SparseMatrix Multiply(SparseMatrix& b);      //矩阵的乘法
	friend ostream& operator<<(ostream& ostr,SparseMatrix& SM); //矩阵的输出重载函数
	friend istream& operator>>(istream& istr,SparseMatrix& SM); //矩阵的输入重载函数
};
SparseMatrix::SparseMatrix(int maxSz):maxTerms(maxSz){     //构造函数:构造一个大小为maxTerm的三元组,行列数和非零元素个数都置零
	if(maxSz<1){
		cerr<<"矩阵初始化错误!"<<endl;
		exit(1);
	}
	smArray=new Trituple[maxSz];
	assert(smArray!=NULL);
	Rows=Cols=Terms=0;
}
SparseMatrix::SparseMatrix(SparseMatrix& SM){  //复制构造函数
	Rows=SM.Rows;      //赋值矩阵的性质
	Cols=SM.Cols;
	Terms=SM.Terms;
	maxTerms=SM.maxTerms;
	smArray=new Trituple[maxTerms];  //构造三元组并赋与SM相同的值
	assert(smArray!=NULL);
	for(int i=0;i<Terms;i++)
		smArray[i]=SM.smArray[i];
}
SparseMatrix::~SparseMatrix(){   //析构函数:释放所有存储
	delete[]smArray;
}
SparseMatrix& SparseMatrix::operator=(SparseMatrix& SM){ //赋值运算符重载
	Rows=SM.Rows;      //元素性质的赋值
	Cols=SM.Cols;
	Terms=SM.Terms;
	maxTerms=SM.maxTerms;
	for(int i=0;i<Terms;i++)      //三元组所有元素赋值
		smArray[i]=SM.smArray[i];
	return *this;    //返回的是对调用该函数的对象的引用,需显式使用this指针;
}
ostream& operator<<(ostream& ostr,SparseMatrix& SM){  //输出运算符重载 (为啥代模板就不能调用row? )
	ostr<<"# Rows="<<SM.Rows<<endl;    //输出该矩阵的性质
	ostr<<"# Cols="<<SM.Cols<<endl;
	ostr<<"# Terms="<<SM.Terms<<endl;
	for(int i=0;i<SM.Terms;i++)   //输出该矩阵非零元素的位置及值
		ostr<<i+1<<": "<<"SM<"<<SM.smArray[i].row<<","<<SM.smArray[i].col<<">="<<
		SM.smArray[i].value<<endl;
	return ostr;
}
istream& operator>> (istream& istr,SparseMatrix& SM){  //输入运算符重载
	cout<<"Please enter number of rows,columns,and terms of Matrix"<<endl;
	istr>>SM.Rows>>SM.Cols>>SM.Terms;  //输入元素的性质
	if(SM.Terms>SM.maxTerms){
		cerr<<"Numbers of Terms overflow!"<<endl;
		exit(1);
	}
	for(int i=0;i<SM.Terms;i++){   //依次输入非零元素的坐标和值
		cout<<"Enter row,column,and value of term:"<<i+1<<endl;
		cin>>SM.smArray[i].row>>SM.smArray[i].col>>SM.smArray[i].value;
	}
	return istr;
}
/*SparseMatrix SparseMatrix::Transpose(){ //转置函数
	SparseMatrix b(maxTerms);
	b.Rows=Rows;
	b.Cols=Cols;
	b.Terms=Terms;
	b.maxTerms=maxTerms;
	if(Terms>0){
		int i,k,CurrentB=0;
		for(k=0;k<b.Cols;k++)     
			for(i=0;i<Terms;i++)
				if(smArray[i].col==k){
					b.smArray[CurrentB].row=smArray[i].col;
					b.smArray[CurrentB].col=smArray[i].row;
					b.smArray[CurrentB].value=smArray[i].value;
					CurrentB++;
				}
	}
	return b;
}*/
SparseMatrix SparseMatrix::Transpose(){   //转置函数
	int *rowSize=new int[Cols]; //转置矩阵每行非零元素的个数
	int *rowStart=new int[Cols]; //转置矩阵每行第一个非零元素对应其三元组的下标
	SparseMatrix b(maxTerms); //转置后的矩阵对应的三元组
	b.Rows=Rows;       //b的性质
	b.Cols=Cols;
	b.Terms=Terms;
	b.maxTerms=maxTerms;
	if(Terms>0){  
		int i,j,CurrentB=0;
		for(i=0;i<Cols;i++)     //对rowSize数组赋值
			rowSize[i]=0;
		for(i=0;i<Terms;i++)
			rowSize[smArray[i].col]++;
		rowStart[0]=0;        //对rowStart数组赋值
		for(i=1;i<b.Rows;i++)
			rowStart[i]=rowStart[i-1]+rowSize[i-1];
		for(i=0;i<Terms;i++){ //遍历三元组a,把各个元素按rowStart数组存在b中相应的位置
			j=rowStart[smArray[i].col]; //a数组中行号按从小到大的顺序排列,所以相同列最先遇到的元素肯定处在相应转置矩阵相应行中的最前面
			b.smArray[j].row=smArray[i].col; //把该元素按照找到的下标j存入b中
			b.smArray[j].col=smArray[i].row;
			b.smArray[j].value=smArray[i].value;
			rowStart[smArray[i].col]++;  //因为该值已经存入b,所以转置矩阵的该行下一个元素在b中对应的下标为rowStart[smArray[i].col]++;
		}
	}
	delete[] rowSize; //释放new申请的存储空间
	delete[] rowStart;
	return b;
}
SparseMatrix SparseMatrix::Add(SparseMatrix& b){   //转置矩阵的加法
	SparseMatrix Result(Rows*Cols);     //结果存于Result里面
	if(Rows!=b.Rows||Cols!=b.Cols){    //规格相同的矩阵才能相加
		cout<<"Incompatible matrices"<<endl;
		return Result;
	}
	Result.Rows=Rows;  
	Result.Cols=Cols;
	Result.Terms=0;
	Result.maxTerms=Rows*Cols;
	int i=0,j=0,index_a,index_b; //i:遍历a三元组;index_a:当前所指的a中元素在矩阵中的位置;
	while(i<Terms&&j<b.Terms){
	index_a=smArray[i].row*Cols+smArray[i].col;
	index_b=b.smArray[j].row*b.Cols+b.smArray[i].col;
	if(index_a<index_b){      //当前所指的a,b中两个元素,a中元素位置在前
		Result.smArray[Result.Terms].row=smArray[i].row;   //直接把a的元素放在Result里面
		Result.smArray[Result.Terms].col=smArray[i].col;
		Result.smArray[Result.Terms].value=smArray[i].value;
		i++; //i指针指向a中下一个元素
	}
	if(index_a>index_b){
		Result.smArray[Result.Terms].row=b.smArray[j].row;
		Result.smArray[Result.Terms].col=b.smArray[j].col;
		Result.smArray[Result.Terms].value=b.smArray[j].value;
		j++;
	}
	if(index_a==index_b){  //位置相同
		if(smArray[i].value+b.smArray[j].value){   //如果两个值相加的和不为零
					Result.smArray[Result.Terms].row=smArray[j].row;   //把相加的结果放在Result中
		            Result.smArray[Result.Terms].col=smArray[j].col;
		            Result.smArray[Result.Terms].value=smArray[i].value+b.smArray[j].value;
					i++;
					j++;
		}
	}
	Result.Terms++;  //存一个元素,非零元素的个数+1;
	}
	for(;i<Terms;i++){       //b中元素已经遍历完,把a剩余的元素放入Result里面,此时i所指的第一个元素位置肯定在b中最后一个元素后面
		Result.smArray[Result.Terms].row=smArray[i].row;
		Result.smArray[Result.Terms].col=smArray[i].col;
		Result.smArray[Result.Terms].value=smArray[i].value;
		i++;
		Result.Terms++;
	}
	for(;j<b.Terms;j++){
		Result.smArray[Result.Terms].row=b.smArray[j].row;
		Result.smArray[Result.Terms].col=b.smArray[j].col;
		Result.smArray[Result.Terms].value=b.smArray[j].value;
		j++;
	    Result.Terms++;
	}
	return Result;
}
SparseMatrix SparseMatrix::Multiply(SparseMatrix& b){  //矩阵的乘法
	SparseMatrix Result(Rows*b.Cols);      //存放矩阵相乘的结果
	if(Cols!=b.Rows){         //两个矩阵能相乘的先决条件:第一个的列数等于第二个的行数
		cerr<<"Incompatible matrices"<<endl;
		return Result;
	}
	int *rowSize=new int[b.Rows];   //b矩阵每行的非零元素个数
	int *rowStart=new int[b.Rows+1];    //b矩阵每行第一个非零元素在b中的下标;为何加一?
	int *temp=new int[b.Cols];  // 暂时存放Result每一行每个元素的运算结果
	int i,Current,lastInResult,RowA,ColA,ColB;  //Current:a的指针; lastInResult:Result的指针
	for(i=0;i<b.Rows;i++)    //对roeSize数组赋值
		rowSize[i]=0;
	for(i=0;i<b.Terms;i++)
		rowSize[b.smArray[i].row]++;
	rowStart[0]=0;      //对rowStart数组赋值
	for(i=1;i<b.Rows;i++)
		rowStart[i]=rowStart[i-1]+rowSize[i-1];
	Current=0;   //从下标0开始遍历a
	lastInResult=-1; //赋初值-1是为了计算方便,看完代码即可了解
	while(Current<Terms){  //遍历三元组a的每一个元素
	RowA=smArray[Current].row; //取得第一个元素的所在行
	for(i=0;i<b.Cols;i++) //把temp数组赋初值为0;
		temp[i]=0;
	while(Current<Terms&&smArray[Current].row==RowA){ //对该行的所有元素进行操作
		ColA=smArray[Current].col; //该元素所在的列ColA就是该元素对应相乘的b中元素的行数
		for(i=rowStart[ColA];i<rowStart[ColA+1];i++){ //遍历b中该行的所有元素
			ColB=b.smArray[i].col; //a的该元素与b中对应行第ColB列的元素相乘的结果应该被放到temp[ColB]中;
			temp[ColB]+=smArray[Current].value*b.smArray[i].value;
		}
		Current++; //a中该元素的已经完成使命,指向a中下一个元素
	}
	for(i=0;i<b.Cols;i++){  //把该行的运算结果存入Result里面
		if(temp[i]!=0){
		lastInResult++;
		Result.smArray[lastInResult].row=smArray[Current].row;
		Result.smArray[lastInResult].col=i;
		Result.smArray[lastInResult].value=temp[i];
		}
	}
}
	Result.Rows=Rows;     //对Result的性质进行赋值操作
	Result.Cols=b.Cols;
	Result.Terms=lastInResult+1;
	delete[] rowSize; //释放new创建的存储空间
	delete[] rowStart;
	delete[] temp;
	return Result;
}
	



  • 24
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会主席、北京市人民代表。他是我国计算机普及和高校计算机基础教育开拓者之一,现任全国高等院校计算机基础教育研究会会长、教育部全国计算机应用技术证书考试委员会主任委员。 谭浩强教授创造了3个世界纪录:(1)20年来他(及和他人合作)共编著出版了130本计算机著作,此外主编了250多本计算机书籍,是出版科技著作数量最多的人。(2)他编著和主编的书发行量超过4500万册,是读者最多的科技作家。我国平均每30人、知识分子每1.5人就拥有1本谭浩强教授编著的书。(3)他和别人合作编著的《BASIC语言》发行了1200万册,创科技书籍发行量的世界纪录。此外,他编著的《C程序设计》发行了600万册。他曾在中央电视台主讲了BASIC,FORTRAN,COBOL,Pascal,QBASIC,C,Visual Basic七种计算机语言,观众超过300万人。 在我国学习计算机的人中很少有不知道谭浩强教授的。他善于用容易理解的方法和语言说明复杂的概念。许多人认为他开创了计算机书籍贴近大众的新风,为我国的计算机普及事业做出了重要的贡献。 谭浩强教授曾获全国高校教学成果国家级奖、国家科技进步奖,以及北京市政府授予的“有突出贡献专家”称号。《计算机世界》报组织的“世纪评选”把他评为我国“20世纪最有影响的IT人物”10个人之一(排在第2位)。他的功绩是把千百万群众带入计算机的大门。 1 C语言概述 1.1 C语言的发展过程 1.2 当代最优秀的程序设计语言 1.3 C语言版本 1.4 C语言的特点 1.5 面向对象的程序设计语言 1.6 C和C++ 1.7 简单的C程序介绍 1.8 输入和输出函数 1.9 C源程序的结构特点 1.10 书写程序时应遵循的规则 1.11 C语言的字符集 1.12 C语言词汇 1.13 Turbo C 2.0 集成开发环境的使用 1.13.1 Turbo C 2.0 简介和启动 1.13.2 Turbo C 2.0 集成开发环境 1.13.3 File菜单 1.13.4 Edit 菜单 1.13.5 Run 菜单 1.13.6 Compile 菜单 11.13.7 Project 菜单 1.13.8 Options菜单 1.13.9 Debug 菜单 1.13.10 Break/watch 菜单 1.13.11 Turbo C 2.0 的配置文件 2 程序的灵魂—算法 2.1 算法的概念 21 2.2 简单算法举例 21 2.3 算法的特性 24 2.4 怎样表示一个算法 24 2.4.1 用自然语言表示算法 24 2.4.2 用流程图表示算法 24 2.4.3 三种基本结构和改进的流程图 28 2.4.4 用N-S 流程图表示算法 29 2.4.5 用伪代码表示算法 30 2.4.6 用计算机语言表示算法 31 2.5 结构化程序设计方法 31 3 数据型、运算符与表达式 3.1 C语言的数据型 32 3.2 常量与变量 33 23.2.1 常量和符号常量 33 3.2.2 变量 33 3.3 整型数据 34 3.3.1 整型常量的表示方法 34 3.3.2 整型变量 35 3.4 实型数据 37 3.4.1 实型常量的表示方法 37 3.4.2 实型变量 38 3.4.3 实型常数的型 39 3.5 字符型数据 39 3.5.1 字符常量 39 3.5.2 转义字符 39 3.5.3 字符变量 40 3.5.4 字符数据在内存中的存储形式及使用方法 41 3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 33.10 逗号运算符和逗号表达式 48 3.11 小结 49 3.11.1 C的数据型 49 3.11.2 基本型的分及特点 49 3.11.3 常量后缀 49 3.11.4 常量型 49 3.11.5 数据型转换 49 3.11.6 运算符优先级和结合性 50 表达式 50 4 最简单的 C程序设计—顺序程序设计 4.1 C语句概述 51 4.2 赋值语句 53 4.3 数据输入输出的概念及在 C 语言中的实现 54 4.4 字符数据的输入输出 54 4.4.1 putchar 函数(字符输出函数) 54 4.4.2 getchar函数(键盘输入函数) 55 4.5 格式输入与输出 55 4.5.1 printf 函数(格式输出函数) 56 4.5.2 scanf函数(格式输入函数)
稀疏矩阵转置是将稀疏矩阵的行列互换得到新的矩阵。 在C语言中,可以使用三元组表示法来存储稀疏矩阵。三元组表示法包括三个数组:行索引数组、列索引数组和值数组。其中,行索引数组存储非零元素所在的行号,列索引数组存储非零元素所在的列号,值数组存储非零元素的值。 稀疏矩阵转置的基本思路是遍历原始稀疏矩阵,将每个非零元素的行列互换后存储到新的稀疏矩阵中。 下面是一个示例代码实现: ```c #include<stdio.h> #define MAX_TERMS 100 typedef struct { int row; int col; int value; } Element; void transpose(Element a[], Element b[]) { int n, m, terms, i, j, currentB; n = a[0].row; m = a[0].col; terms = a[0].value; b[0].row = m; b[0].col = n; b[0].value = terms; if (terms > 0) { currentB = 1; for (j = 0; j < m; j++) { for (i = 1; i <= terms; i++) { if (a[i].col == j) { b[currentB].row = a[i].col; b[currentB].col = a[i].row; b[currentB].value = a[i].value; currentB++; } } } } } int main() { int n, m, i, j, count = 1; printf("Enter the number of rows and columns: "); scanf("%d %d", &n, &m); Element a[MAX_TERMS], b[MAX_TERMS]; a[0].row = n; a[0].col = m; printf("Enter the elements of the matrix: \n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { int element; scanf("%d", &element); if (element != 0) { a[count].row = i; a[count].col = j; a[count].value = element; count++; } } } transpose(a, b); printf("\nOriginal sparse matrix:\n"); for (i = 0; i <= a[0].value; i++) { printf("%d\t%d\t%d\n", a[i].row, a[i].col, a[i].value); } printf("\nTransposed sparse matrix:\n"); for (i = 0; i <= b[0].value; i++) { printf("%d\t%d\t%d\n", b[i].row, b[i].col, b[i].value); } return 0; } ``` 这段代码中,我们首先定义了一个 `Element` 结构体来表示稀疏矩阵的非零元素。然后,使用 `transpose` 函数来实现稀疏矩阵的转置操作。最后,在 `main` 函数中,我们可以输入稀疏矩阵的行列数和元素,并输出原始稀疏矩阵和转置后的稀疏矩阵。 希望这段代码能帮助到你!如果有任何问题,请随时向我提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值