原题链接:数据结构-行逻辑链接的矩阵乘法
解题思路:
① 只需要计算两矩阵非0元素间的乘法;
② 使用行逻辑链接可得到该行首个非0元位置,也可以间接得到该行非0元个数;
③ 在行逻辑链接的基础上,可以成行确定Q的元素,即需要M该行的遍历 + N全行的遍历。
参考代码:
#include<stdio.h> #include<malloc.h> #include<string.h> typedef struct Triple { int i, j; // 所在行、列 int data; // 数值 } Triple; typedef struct RLSMatrix { Triple *data; int *rpos; // 记录每行首个非0元的位置 int mu, nu, tu; // 行、列、非0元个数 } RLSMatrix; // 创建行逻辑链接的顺序表 void CreateRLSMatrix(RLSMatrix *M); // 矩阵乘法,在M中遍历非0元进行 void MultRLSMatrix(RLSMatrix *M, RLSMatrix *N, RLSMatrix *Q); // 按行输出矩阵 void DisplayRLSMatrix(RLSMatrix *Q); int main() { RLSMatrix M, N, Q; M.data = NULL; M.rpos = NULL; N.data = NULL; N.rpos = NULL; Q.data = NULL; Q.rpos = NULL; CreateRLSMatrix(&M); CreateRLSMatrix(&N); MultRLSMatrix(&M, &N, &Q); DisplayRLSMatrix(&Q); return 0; } void CreateRLSMatrix(RLSMatrix *M) { int i, j, data, size; M->tu = 1; scanf("%d%d", &M->mu, &M->nu); M->data = (Triple *)malloc(sizeof(Triple) * M->nu * 2); M->rpos = (int *)malloc(sizeof(int) * (M->mu + 1)); size = M->nu * 2; for (i = 1; i <= M->mu; i++) { M->rpos[i] = M->tu; // 该行首个非0元位置在上一行输入完时确定 for (j = 1; j <= M->nu; j++) { scanf("%d", &data); if (data) { // 存放非0元 // 注意这里第0个位置不存放非0元,从第1个开始,和行逻辑对应 M->data[M->tu].i = i; M->data[M->tu].j = j; M->data[M->tu++].data = data; } } if (size - M->tu < M->nu) { M->data = (Triple *)realloc(M->data, sizeof(Triple) * (size + M->nu)); size += M->nu; } } M->tu--; // 此前始终比非0元个数大1,此时减去 } void MultRLSMatrix(RLSMatrix *M, RLSMatrix *N, RLSMatrix *Q) { int i, j, k1, k2, k3, k4, row, col, size, *temp; Q->mu = M->mu; Q->nu = N->nu; Q->tu = 0; Q->data = (Triple *)malloc(sizeof(Triple) * Q->nu * 2); size = Q->nu * 2; // temp暂时存放乘积结果,每次存放Q[i]行的结果,个数为N的列数 temp = (int *)malloc(sizeof(int) * (Q->nu + 1)); for (row = 1; row <= M->mu; row++) { // 遍历M每行的非0元 memset(temp, 0, sizeof(int) * (Q->nu + 1)); // 每行都需要将temp重置 k1 = M->rpos[row]; // 获取该行首个非0元 if (row == M->mu) { k2 = M->tu + 1; // 若是最后一行,直接遍历完 } else { k2 = M->rpos[row + 1]; // 否则,遍历完到下一行首个非0元之前 } // M中从k1遍历到k2 while (k1 < k2) { j = M->data[k1].j; // 获取非0元在M中的所在列 k3 = N->rpos[j]; // 找到对应N的那行 if (j == N->mu) { k4 = N->tu + 1; } else { k4 = N->rpos[j + 1]; } // 对M中每个非0元取所在列,在N中找到对应行非0元,记录分积 while (k3 < k4) { col = N->data[k3].j; // 获取N中该非0元所在列 temp[col] += M->data[k1].data * N->data[k3].data; k3++; } k1++; } // 当M的该行遍历完成,Q的该行元素全部确定 for (i = 1; i <= Q->nu; i++) { if (temp[i]) { // 只存放非0元 Q->data[++Q->tu].i = row; Q->data[Q->tu].j = i; Q->data[Q->tu].data = temp[i]; } } // 偷懒,没有进行Q的行逻辑链接。 if (size - Q->tu < Q->nu) { Q->data = (Triple *)realloc(Q->data, sizeof(Triple) * (size + Q->nu)); size += Q->nu; } } } void DisplayRLSMatrix(RLSMatrix *Q) { int i, j, k = 1; for (i = 1; i <= Q->mu; i++) { for (j = 1; j <= Q->nu; j++) { if (Q->data[k].i == i && Q->data[k].j == j) { printf("%d ", Q->data[k++].data); } else { printf("0 "); } } printf("\n"); } }
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复