题目信息
数据压缩是提高传输、存储效率一种技术。
本实验要求实现两个稀疏矩阵相乘积的算法。其中稀疏矩阵非零元素数量小于100.
输入
第1个稀疏矩阵的行数,列数,非零元个数(三个数都大于0),三元组
第2个稀疏矩阵的行数,列数,非零元个数(三个数都大于0),三元组
以行为主序输入稀疏矩阵三元组表
输出
乘积矩阵的行数
列数
非零元个数(三个数都大于0)
三元组
测试样例
3
4
4
1 1 3
1 4 5
2 2 -1
3 1 2
4
2
4
1 2 2
2 1 1
3 1 -2
3 2 4
3
2
3
1,2,6
2,1,-1
3,2,4
解答
#include<stdio.h>
typedef struct
{
int i, j;
int e;
} Node;
typedef struct
{
Node nodes[105];
int rpos[105];//各行第一个非零元的位置表
int m, n, t;
} Matrix;
int main()
{
//freopen("/Users/zhj/Downloads/test.txt", "r", stdin);
Matrix A, B;
scanf("%d%d%d", &A.m, &A.n, &A.t);
for (int i = 1; i <= A.t; i++)
{
scanf("%d%d%d", &A.nodes[i].i, &A.nodes[i].j, &A.nodes[i].e);
}
int num[1000];
for (int col = 1; col <= A.m; col++)
{
num[col] = 0;
}
for (int i = 1; i <= A.t; i++)
{
num[A.nodes[i].i]++;
}
A.rpos[1] = 1;
for (int col = 2; col <= A.m; col++)
{
A.rpos[col] = A.rpos[col - 1] + num[col - 1];
}
scanf("%d%d%d", &B.m, &B.n, &B.t);
for (int i = 1; i <= B.t; i++)
{
scanf("%d%d%d", &B.nodes[i].i, &B.nodes[i].j, &B.nodes[i].e);
}
for (int col = 1; col <= B.m; col++)
{
num[col] = 0;
}
for (int i = 1; i <= B.t; i++)
{
num[B.nodes[i].i]++;
}
B.rpos[1] = 1;
for (int col = 2; col <= B.m; col++)
{
B.rpos[col] = B.rpos[col - 1] + num[col - 1];
}
Matrix Q;
Q.m = A.m;
Q.n = B.n;
Q.t = 0;//创建答案矩阵
if (A.t * B.t != 0)
{//Q是非零矩阵
for (int arow = 1; arow <= A.m; arow++)
{//处理A的每一行
int ctemp[105] = {0};
Q.rpos[arow] = Q.t + 1;
int tp;//tp是下一行元素在nodes表中位置
if (arow < A.m)
{
tp = A.rpos[arow + 1];
}
else
{
tp = A.t + 1;
}
for (int p = A.rpos[arow]; p < tp; p++)
{//对当前行中每一个非零元,既从当前在nodes表中位置找到下一行元素在nodes表的位置
int brow = A.nodes[p].j;//此为A表中的纵向位置值,在B表中找相应的行号即可
int t;//t仍然为下一行的位置
if (brow < B.m)
{
t = B.rpos[brow + 1];
}
else
{
t = B.t + 1;
}
for (int q = B.rpos[brow]; q < t; q++)
{
int ccol = B.nodes[q].j;//Q中的纵坐标是以B元素中的j来说话的
ctemp[ccol] += A.nodes[p].e * B.nodes[q].e;
}
}
for (int ccol = 1; ccol <= Q.n; ccol++)
{//压缩存储该行的非零元
if (ctemp[ccol])
{//如果此处有值的话
Q.t++;//Q的非零元素多了一个
Q.nodes[Q.t].i = arow;//行号为此时遍历的A的行号
Q.nodes[Q.t].j = ccol;//列号为此时正在进行压缩所遍历到有值的地方
Q.nodes[Q.t].e = ctemp[ccol];//累计的和拷贝过来
}
}
}
}
printf("%d\n", Q.m);
printf("%d\n", Q.n);
printf("%d\n", Q.t);
for (int i = 1; i <= Q.t; i++)
{
printf("%d,%d,%d\n", Q.nodes[i].i, Q.nodes[i].j, Q.nodes[i].e);
}
return 0;
}
想法
对于A中每个元素A.nodes[p](p=1,2,...,A.t)
,找到N中所有满足条件A.nodes[p].j = B.nodes.i
的元素B.nodes[q]
,求得A.nodes[p].v
和B.nodes[q].v
的乘积.
乘积矩阵Q中每个元素的值是个累积和,这个乘积A.nodes[p].v * B.nodes[q]
,v只是Q[i][j]
中的一部分.为便于操作,应对每个元素设一累计和的变量,其初值为零,然后扫面数组A,求得相应元素的乘积并累加到适当的求累计和的变量上