#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已经到底,另一个仍未到底的时候,结果三元组表仅与未到底的三元组表有关,而此时,若我们仍简单地继续比较两个三元组表的信息,将会产生错误结果
-
因为我们知道三元组表多余的元素都为零,若此时再比较,结果矩阵将全部存入零。