基于三元组表的矩阵加法与乘法


#include<stdio.h>
#include<stdlib.h>

typedef struct {
	int i, j;
	int value;//三元组表有三个信息,对应为第i行,第j列,以及该元素元素值 
}tuple;
struct sparmattp {//m,n分别对应矩阵的规模 ,t代表三元组表一共放了多少个元素 
	int m, n, t; 
	tuple data[100];
};
void matrixset(struct sparmattp& a) {
	int cnt = 0;
	int i, j;
	int m, n, value;

	printf("Please input the row and the coloum of the matrix:\n");
	scanf("%d%d", &m, &n);
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			scanf("%d", &value);//依次读入矩阵元素,如果该元素不为0,存入三元组表 
			if (value != 0) {
				a.data[cnt].value = value;
				a.data[cnt].i = i;
				a.data[cnt].j = j;//存下当前元素值,所在的行、列 
				cnt++;
			}
		}
	}
	a.m = m;
	a.n = n;
	a.t = cnt;
}
void matrixset2(int row, int coloum, struct sparmattp& a) {//该函数与前一个函数功能相似,只是这个是通过传参数来得知矩阵的规模,而不是通过键盘输入 
	int cnt = 0;
	int i, j;
	int m, n, value = 0;

	m = row;
	n = coloum;
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			if (value == 0) {
				a.data[cnt].value = value;
				a.data[cnt].i = i;
				a.data[cnt].j = j;
				cnt++;
			}
		}
	}
	a.m = m;
	a.n = n;
	a.t = cnt;
}
int find(struct sparmattp& a, int i, int j) {//该函数用于寻找矩阵对应第i行第j列的元素 ,返回值即元素值 
	int cnt;
	for (cnt = 0; cnt < a.t; cnt++) {
		if (a.data[cnt].i == i && a.data[cnt].j == j) {
			return a.data[cnt].value;
		}
	}
	return 0;
}
/*
	矩阵加法定义的是矩阵a+矩阵b,能相加的条件为:两者规模相等,即rowa=rowb,colouma=coloumb。
	因为我们是使用三元表存放的矩阵,那么我们需要解决的问题则变为如何通过三元组表来进行矩阵加法
	我们可以通过cnt来得知两个矩阵分别有多少个元素,
	不满足相加条件时,先存小的那一个,然后小的cnt++;
*/
void matrixadd(struct sparmattp& a, struct sparmattp& b, struct sparmattp& c) {
	int cnt1 = 0, cnt2 = 0, cnt3 = 0;
	if (a.m == b.m&&a.n == b.n) {//判断能否相加,相加的条件是矩阵规模相等
		while (cnt1 < a.t && cnt2 < b.t) {//相加结束的条件是把矩阵所有元素遍历完
			if (a.data[cnt1].i == b.data[cnt2].i) {//如果两个矩阵对应的三元组表的当前元素所在的行相等
				if (a.data[cnt1].j == b.data[cnt2].j) {//如果列也相等,当然直接相加即可
					c.data[cnt3].value = a.data[cnt1].value + b.data[cnt2].value;
					c.data[cnt3].i = a.data[cnt1].i;
					c.data[cnt3].j = a.data[cnt1].j;
					cnt1++;
					cnt2++;
					cnt3++;
				}
				else if (a.data[cnt1].j > b.data[cnt2].j) {//列不相等,比较哪个列更小,因为我们是从左到右来建立三元组表的,把所在列更小的那一个元素存入新的三元组表中
					c.data[cnt3].value = b.data[cnt2].value;
					c.data[cnt3].i = b.data[cnt2].i;
					c.data[cnt3].j = b.data[cnt2].j;
					cnt3++;
					cnt2++;
				}
				else if (a.data[cnt1].j < b.data[cnt2].j) {
					c.data[cnt3].value = a.data[cnt1].value;
					c.data[cnt3].i = a.data[cnt1].i;
					c.data[cnt3].j = a.data[cnt1].j;
					cnt3++;
					cnt1++;
				}
			}//到这里是行相等的情况,从下面开始,将讨论行不相等的时候,相加结果的三元组表元素的存放
			else if (a.data[cnt1].i > b.data[cnt2].i) {//与上面讨论的一致,我们选取小的那一个,把它存到新的三元组表中
				c.data[cnt3].value = b.data[cnt2].value;
				c.data[cnt3].i = b.data[cnt2].i;
				c.data[cnt3].j = b.data[cnt2].j;
				cnt3++;
				cnt2++;
			}
			else if (a.data[cnt1].i < b.data[cnt2].i) {
				c.data[cnt3].value = a.data[cnt1].value;
				c.data[cnt3].i = a.data[cnt1].i;
				c.data[cnt3].j = a.data[cnt1].j;
				cnt3++;
				cnt1++;
			}
		}
		while (cnt1 == a.t && cnt2 < b.t) {
			c.data[cnt3].i = b.data[cnt2].i;
			c.data[cnt3].j = b.data[cnt2].j;
			c.data[cnt3].value = b.data[cnt2].value;
			cnt3++;
			cnt2++;
		}
		while (cnt1 < a.t && cnt2 == b.t) {
			c.data[cnt3].i = a.data[cnt1].i;
			c.data[cnt3].j = a.data[cnt1].j;
			c.data[cnt3].value = a.data[cnt1].value;
			cnt3++;
			cnt1++;
		}
		c.m = a.m;
		c.n = a.n;
		c.t = cnt3;//更新结果三元组表的信息
	}
	else {
		printf("你输入的两个矩阵不能相加!\n");
	}
}
/*
	矩阵1(m1*n1)*矩阵二(m2*n2)=矩阵3(m1*n2)前提是n1==m2
	cij=Σai*bj;
*/
void matrixmultiply(struct sparmattp& a, struct sparmattp& b, struct sparmattp& c) {
	int sum = 0;
	int cnt = 0;
	int i, j, k;
	if (a.n == b.m) {
		for (i = 0; i < a.m; i++) {
			for (j = 0; j < b.n; j++) {
				sum = 0;
				for (k = 0; k < a.n; k++) {
					sum = sum + find(a, i, k)*find(b, k, j);
				}//找出对应的aik以及bkj
				c.data[cnt].value = sum;
				c.data[cnt].i = i;
				c.data[cnt].j = j;
				cnt++;
			}
		}	
		c.m=a.m;
		c.n=b.n;
		c.t=cnt;		
	}
	else {
		printf("你输入的矩阵不满足乘法条件!\n");
	}
}
void printmatirx(struct sparmattp& ma) {
	int i, j, cnt = 0;
	printf("矩阵打印:\n");
	for (i = 0; i < ma.m; i++) {
		for (j = 0; j < ma.n; j++) {
			if (ma.data[cnt].i == i && ma.data[cnt].j == j) {
				printf("%d ", ma.data[cnt].value);
				cnt++;
			}
			else { printf("0 "); }

		}
		printf("\n");
	}//用来输出矩阵的代码
}
int main() {
	struct sparmattp ma, mb, mc;
	int m, n;
	matrixset(ma);
	matrixset(mb);
	matrixset2(ma.m, ma.n, mc);
	matrixadd(ma, mb, mc);
	printmatirx(mc);
	matrixmultiply(ma, mb, mc);
	printmatirx(mc);

	return 0;
}
  • 在编写加法函数的过程中,我们发现对退出循环的条件需要有更高的要求,而不是仅仅只是两个cnt同时到底,因为如果当一个cnt已经到底,另一个仍未到底的时候,结果三元组表仅与未到底的三元组表有关,而此时,若我们仍简单地继续比较两个三元组表的信息,将会产生错误结果
  • 因为我们知道三元组表多余的元素都为零,若此时再比较,结果矩阵将全部存入零。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值