您的位置:首页 > 理论基础 > 数据结构算法

第八周(2) 项目3.2-稀疏矩阵的三元组表示的实现及应用

2017-10-19 11:11 459 查看
【项目 - 稀疏矩阵相加】 

  采用三元组存储稀疏矩阵,设计两个稀疏矩阵相加的运算算法 

提示1:两个行数、列数相同的矩阵可以相加 

提示2:充分利用已经建立好的算法库解决问题

[参考解答1] 
#include <stdio.h>
#include "tup.h"
bool MatAdd(TSMatrix a,TSMatrix b,TSMatrix &c)
{
int i,j;
ElemType va,vb,vc;
if (a.rows!=b.rows || a.cols!=b.cols)
return false;                        //行数或列数不等时不能进行相加运算
c.rows=a.rows;
c.cols=a.cols;       //c的行列数与a的相同
c.nums=0;
for(i=0; i<M; i++)
for(j=0; j<N; j++)
{
Assign(a,va,i,j);
Assign(b,vb,i,j);
vc=va+vb;
if(vc)
Value(c,vc,i,j);
}
return true;
}

int main()
{
TSMatrix ta,tb,tc;
int A[M]
=
{
{0,0,1,0,0,0,0},
{0,2,0,0,0,0,0},
{3,0,0,0,0,0,0},
{0,0,0,5,0,0,0},
{0,0,0,0,6,0,0},
{0,0,0,0,0,7,4}
};
int B[M]
=
{
{0,0,10,0,0,0,0},
{0,0,0,20,0,0,0},
4000

{0,0,0,0,0,0,0},
{0,0,0,50,0,0,0},
{0,0,20,0,0,0,0},
{0,0,0,10,0,0,4}
};
CreatMat(ta,A);
CreatMat(tb,B);
printf("A:\n");
DispMat(ta);
printf("B:\n");
DispMat(tb);
if(MatAdd(ta, tb, tc))
{
printf("A+B:\n");
DispMat(tc);
}
else
{
printf("相加失败\n");
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

[参考解答2] 

  下面给出的解答,没有利用算法库中已经实现的Assign和Value两个基本运算,而是直接e采取了更为直接的方法去完成。用i和j两个变量扫描三元组a和b,按行序优先的原则进行处理,将结果存放于c中。当a的当前元素和b的当前元素的行号和列号均相等时,将它们的值相加,只有在相加值不为0时,才在c中添加一个新的元素。
#include <stdio.h>
#include "tup.h"
bool MatAdd(TSMatrix a,TSMatrix b,TSMatrix &c)
{
int i=0,j=0,k=0;
ElemType v;
if (a.rows!=b.rows || a.cols!=b.cols)
return 0;        //行数或列数不等时不能进行相加运算
c.rows=a.rows;
c.cols=a.cols;       //c的行列数与a的相同
while (i<a.nums && j<b.nums)         //处理a和b中的每个元素
{
if (a.data[i].r==b.data[j].r)    //行号相等时
{
if(a.data[i].c<b.data[j].c)  //a元素的列号小于b元素的列号
{
c.data[k].r=a.data[i].r;//将a元素添加到c中
c.data[k].c=a.data[i].c;
c.data[k].d=a.data[i].d;
k++;
i++;
}
else if (a.data[i].c>b.data[j].c)//a元素的列号大于b元素的列号
{
c.data[k].r=b.data[j].r;      //将b元素添加到c中
c.data[k].c=b.data[j].c;
c.data[k].d=b.data[j].d;
k++;
j++;
}
else                    //a元素的列号等于b元素的列号
{
v=a.data[i].d+b.data[j].d;
if (v!=0)           //只将不为0的结果添加到c中
{
c.data[k].r=a.data[i].r;
c.data[k].c=a.data[i].c;
c.data[k].d=v;
k++;
}
i++;
j++;
}
}
else if (a.data[i].r<b.data[j].r) //a元素的行号小于b元素的行号
{
c.data[k].r=a.data[i].r;      //将a元素添加到c中
c.data[k].c=a.data[i].c;
c.data[k].d=a.data[i].d;
k++;
i++;
}
else                              //a元素的行号大于b元素的行号
{
c.data[k].r=b.data[j].r;      //将b元素添加到c中
c.data[k].c=b.data[j].c;
c.data[k].d=b.data[j].d;
k++;
j++;
}
}
while (i<a.nums)         //a中尚有元素时
{
c.data[k].r=a.data[i].r;//将a元素添加到c中
c.data[k].c=a.data[i].c;
c.data[k].d=a.data[i].d;
k++;
i++;
}
while (j<b.nums)         //b中尚有元素时
{
c.data[k].r=b.data[j].r;      //将b元素添加到c中
c.data[k].c=b.data[j].c;
c.data[k].d=b.data[j].d;
k++;
j++;
}
c.nums=k;
return true;
}

int main()
{
TSMatrix ta,tb,tc;
int A[M]
=
{
{0,1,0,0,0,0,0},
{0,2,0,0,0,0,0},
{3,0,0,0,0,0,0},
{0,0,0,5,0,0,0},
{0,0,0,0,6,0,0},
{0,0,0,0,0,7,4}
};
int B[M]
=
{
{0,0,10,0,0,0,0},
{0,0,0,20,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,50,0,0,0},
{0,0,20,0,0,0,0},
{0,0,0,10,0,0,4}
};
CreatMat(ta,A);
CreatMat(tb,B);
printf("A:\n");
DispMat(ta);
printf("B:\n");
DispMat(tb);
if(MatAdd(ta, tb, tc))
{
printf("A+B:\n");
DispMat(tc);
}
else
{
printf("相加失败\n");
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

  对比两种方案,“参考解答1”利用Assign和Value两个基本运算的方案,可以在只知道“矩阵加法是对应位置的元素相加”的基础上就可以求解;而“参考解答2”则不得不关注在数据存储层面的细节,以致于矩阵加法的规则都不容易看出来了。“参考解答2”中繁杂的代码,违反了程序设计中诸多的原则(例如模块化),相对“参考解答1”的简洁中透出的优雅,该不是学习者效仿的思维。

附:1楼评论中带bug的解答,原参考解答2。重点观察少了
while (i<a.nums)
while
(j<b.nums)
两个循环,当a和b的最后一个元素不在同一行同一列时,会丢数据的。这个bug的漏网,和main函数中采用的测试数据不够好有关,让两个矩阵非0元素在同一行同一列,忽略了“边界”数据的重要性。 

  与此同时,再次体会参考解答1的好处,缺少了一层抽象,对应的就是处处要考虑细节。智者千虑,必有一失,还是要运用上工程中的原则为好。
#include <stdio.h>
#include "tup.h"
bool MatAdd(TSMatrix a,TSMatrix b,TSMatrix &c)
{
int i=0,j=0,k=0;
ElemType v;
if (a.rows!=b.rows || a.cols!=b.cols)
return 0;        //行数或列数不等时不能进行相加运算
c.rows=a.rows;
c.cols=a.cols;       //c的行列数与a的相同
while (i<a.nums && j<b.nums)         //处理a和b中的每个元素
{
if (a.data[i].r==b.data[j].r)    //行号相等时
{
if(a.data[i].c<b.data[j].c)  //a元素的列号小于b元素的列号
{
c.data[k].r=a.data[i].r;//将a元素添加到c中
c.data[k].c=a.data[i].c;
c.data[k].d=a.data[i].d;
k++;
i++;
}
else if (a.data[i].c>b.data[j].c)//a元素的列号大于b元素的列号
{
c.data[k].r=b.data[j].r;      //将b元素添加到c中
c.data[k].c=b.data[j].c;
c.data[k].d=b.data[j].d;
k++;
j++;
}
else                    //a元素的列号等于b元素的列号
{
v=a.data[i].d+b.data[j].d;
if (v!=0)           //只将不为0的结果添加到c中
{
c.data[k].r=a.data[i].r;
c.data[k].c=a.data[i].c;
c.data[k].d=v;
k++;
}
i++;
j++;
}
}
else if (a.data[i].r<b.data[j].r) //a元素的行号小于b元素的行号
{
c.data[k].r=a.data[i].r;      //将a元素添加到c中
c.data[k].c=a.data[i].c;
c.data[k].d=a.data[i].d;
k++;
i++;
}
else                              //a元素的行号大于b元素的行号
{
c.data[k].r=b.data[j].r;      //将b元素添加到c中
c.data[k].c=b.data[j].c;
c.data[k].d=b.data[j].d;
k++;
j++;
}
c.nums=k;
}
return true;
}

int main()
{
TSMatrix ta,tb,tc;
int A[M]
=
{
{0,0,1,0,0,0,0},
{0,2,0,0,0,0,0},
{3,0,0,0,0,0,0},
{0,0,0,5,0,0,0},
{0,0,0,0,6,0,0},
{0,0,0,0,0,7,4}
};
int B[M]
=
{
{0,0,10,0,0,0,0},
{0,0,0,20,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,50,0,0,0},
{0,0,20,0,0,0,0},
{0,0,0,10,0,0,4}
};
CreatMat(ta,A);
CreatMat(tb,B);
printf("A:\n");
DispMat(ta);
printf("B:\n");
DispMat(tb);
if(MatAdd(ta, tb, tc))
{
printf("A+B:\n");
DispMat(tc);
}
else
{
printf("相加失败\n");
}
return 0;
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构
相关文章推荐