5.3矩阵乘积(三元组存储结构)
行逻辑链表的顺序表
为了便于随机存取任意一行的非零元,则需要知道每一行的第一个非零元在三元组表中的位置。为此,可将上节快速转置矩阵中的算法创建的,指示“行”信息的辅助数组cpot固定在稀疏矩阵的存储结构中。称这种"带行链接信息"的三元组表为行逻辑链接的顺序表。
描述如下:
typedef struct{Triple data[MAXSIZE + 1]; //非零元三元组表int rpos[MAXRC + 1]; //各行第一个非零元的位置表int mu, nu, tu; //矩阵的行数、列数和非零元个数
}RLSMatrix;
P·S
这里的MAXSIZE在上一节有交代。这个data[MAXSIZE+1]为什么要加一呢,因为data[0]未用,同样rpos[MAXRC+1]也是这个道理。
我们现在来看在数学里面,两个矩阵做乘积运算应该怎么算。
如下图所示:
P·S:本人字丑,大家将就看吧。
另外大家要知道矩阵相乘的条件:矩阵只有当左边矩阵的列数等于右边矩阵的行数时,它们才可以相乘,乘积矩阵的行数等于左边矩阵的行数,乘积矩阵的列数等于右边矩阵的列数。
这样我们就知道,当一个不用三元组表示的矩阵M(m1行n1列)和一个矩阵n(m2行n2列)相乘时,有一个经典算法,就和上面那数学运算一模一样。
代码如下:
for (i = 1; i <= m1; i++)
{for (j = 1; j <= n2; j++){Q[i][j] = 0;for (k = 1; k <= n1; k++){Q[i][j] += M[i][k] * N[K][j];}}
}
分析下:
因为产生的矩阵是m1行n2列的矩阵,所以第一个for里面限定条件是m1,第二个for限定条件是n2,第三个for就是把第一个矩阵里面的行和第二个矩阵的列相乘并且加起来。这个Q[i][j]的作用就是先把存储到那一块的内存初始化,免得有其他数据影响。
下面,我们的问题来了,当用三元组存储结构时呢?用三元组时我们一般是稀疏矩阵。
也就是说当M和N是稀疏矩阵并用三元组表作存储结构时,不能用上面那个算法。
如下面这个例子:
那么,他们的三元组M.data、N.data和Q.data分别为:
在此补充下rpos
矩阵N的rpos值(代码中会用到)
row | 1 | 2 | 3 | 4 |
rpos[row] | 1 | 2 | 3 | 5 |
矩阵M的rpos值
row | 1 | 2 | 3 |
rpos[row] | 1 | 3 | 4 |
rpos[row]指:第row行中第一个非零元在N.data中的序号。不难理解。大家对照上面的表就能填出来。
下面给出书中的伪代码:
2017年版的严蔚敏版数据结构
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix &Q)
{// 求矩阵乘积Q=M*N,采用行逻辑链接存储表示。int arow, brow, p, q, t, ctemp[30], l, ccol, tp;if (M.nu != N.mu) return ERROR;Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; // Q初始化if (M.tu*N.tu != 0) { // Q是非零矩阵for (arow = 1; arow <= M.mu; ++arow) { // 处理M的每一行for (l = 1; l <= M.nu; ++l) ctemp[l] = 0; // 当前行各元素累加器清零Q.rpos[arow] = Q.tu + 1;if (arow < M.mu) tp = M.rpos[arow + 1];else tp = M.tu + 1;for (p = M.rpos[arow]; p < tp; ++p) { // 对当前行中每一个非零元 brow = M.data[p].j; // 找到对应元在N中的行号if (brow < N.mu) t = N.rpos[brow + 1];else t = N.tu + 1;for (q = N.rpos[brow]; q< t; ++q) {ccol = N.data[q].j; // 乘积元素在Q中列号ctemp[ccol] += M.data[p].e * N.data[q].e;} // for q} // 求得Q中第crow( =arow)行的非零元for (ccol = 1; ccol <= Q.nu; ++ccol) // 压缩存储该行非零元if (ctemp[ccol]) {if (++Q.tu > MAXSIZE) return ERROR;Q.data[Q.tu].i = arow;Q.data[Q.tu].j = ccol;Q.data[Q.tu].e = ctemp[ccol];} // if} // for arow} // if return OK;
} // MultSMatrix
分析下:
这里,我们要有一个思路:在经典算法里面,无论M(i,k)和N(k,j)的值是否为0,都要进行一次乘法运算,而实际上,这两者有一个值不为0时,其乘积也是0.所以,在稀疏矩阵进行运算时,要避免这种无效果操作,只需要在M.data和N.data中找到相应的各对元素(即M.data中的j值和N.data中的i值相等的各元素)乘积即可。
此函数一开始的M.nu!=N.mu就返回ERROR,这就是我刚刚说的矩阵要相乘应该满足的条件。
在if语句M.tu*N.tu!=0,这是为了判断他是不是非0矩阵,如果是非0矩阵,就直接返回。
在这个for(l=1;l<=M.nu;++l)里面这个是把nu是列。这时可能有人会问,为什么nu是列,而注释里面是把当前行各元素累加器清0,原因是他把当前行的元素清0,当前行到底有多少个元素,只能靠列来算。
随后的Q.rpos[arow]=Q.tu+1;这里有网友可能会问两个问题,一个是这个这个Q.rpos[arow]有什么用把后面那个赋值给他有什么含义,第二个就是为什么要Q.tu+1(为什么要总元素+1)。Q.rpos[arow]这个东西就是Q中各行第一个非零元的位置表。Q.tu+1是因为第一个就是1,这里面不可能从0开始。
下面这个if(aow<M.mu)else这个,这个tp是得到了下一行的第一个元素的位置。所以拿他当下面那个for循环的限制条件。
剩下的代码和上面的有很多相似之处,在此不再说明了。
5.3矩阵乘积(三元组存储结构)相关推荐
- c语言三元组求矩阵加法,矩阵相加的算法(存储结构为三元组表)
假设稀疏矩阵A和B均以三元组表作为存储结构.试写出矩阵相加的算法,另设三元组表C存放结果矩阵. 稀疏矩阵的三元组顺序表类型TSMatrix的定义: #define MAXSIZE 20 // 非零元个 ...
- 数据结构 实验14(1-2班):(深入理解索引存储结构)三元组存储的稀疏矩阵建立行列索引并求鞍点
目录 前言: 需求分析: 难点分析: 代码和思路详解: 三元组表的头文件: 建立索引思路: 什么是三元组表的索引: 结合题意实现索引表: 建立索引表的代码实现: 索引表的结构体定义: 索引表的创建思路 ...
- 数据结构——图——存储结构——邻边矩阵
数据结构--图--存储结构--邻边矩阵 考虑到图是由顶点和边或弧两部分组成.合在一起比较困难,那就很自然地考虑到分两个结构来分别存储.顶点不分大小.主次,所以用一个一维数组来存储是很不错的选择.而边或 ...
- 顺序三元组 java_三元组顺序结构实现稀疏矩阵相加,行序优先(Java语言描述)
不用十字链表也可以稀疏矩阵相加时间复杂度最坏情况达到O(tuA + tuB);思路比较简单就不赘述了,代码如下: 三元组: package 行逻辑链接的顺序表实现稀疏矩阵的相乘; public cla ...
- 5.3矩阵的压缩存储(稀疏矩阵转置和快速转置)
在矩阵中有许多值相同的元素或者是零元素.有时为了节省存储空间,可以对这类矩阵进行压缩存储.所谓的压缩存储是指:为多个值相同的元值分配一个存储空间:对零元不分配空间. 5.32稀疏矩阵 在m*n的矩阵中 ...
- 数据结构的学习_4.2 矩阵的压缩存储(对称矩阵)
4.2 矩阵的压缩存储(一) 在有些情况下,矩阵中含有许多值相同或者值为零的元素,如果还按前面的方法来存储这种矩阵,就会产生大量的空间浪费.为了节省存储空间,可以对这类矩阵采用压缩存储. 4.2.1 ...
- 图的存储结构(邻接矩阵和邻接表)
图的存储结构(邻接矩阵和邻接表) 前言: 前面我们学习图的有些定义和术语,对图这个数据结构有了新的见解和认知,让我们理解图结构的知识,今天我们学习图的存储结构,图的存储结构比较多,我们今天主要是学习邻 ...
- 矩阵的压缩存储(随机稀疏矩阵的建立和输出)
实际应用中会有很多利用高阶矩阵的问题,有的高阶矩阵已达到几十万阶,几千亿个元素.然而,多数的高阶矩阵中包含了大量的数值为零的元素,需要对这类矩阵进行压缩存储.因为合理的压缩存储不仅能有效地节省存储空间 ...
- 图1——图的五种存储结构及其初始化
零.说明 本文中,V代表Vertex,即顶点,E代表Edge,即边.什么Vnum,Enum,firstE都按照这个来理解. 原理我是按<大话数据结构>来的,我也解释不好这个原理,就不献丑了 ...
最新文章
- 史上最全SQL优化方案(二)
- matlab 自定义对象,面向对象:MATLAB的自定义类 [MATLAB]
- 解决 vue路由跳转到新页面底部而不是顶部和后退到首页就不让他继续后退了
- UA MATH567 高维统计专题1 稀疏信号及其恢复1 L0-norm minimization
- SAP中负数的表示增强 负号从数字后更改到数字前面
- dedecms 文章回收站 记得及时清理
- Android Service和Binder、AIDL
- [XSY4220] 九万步(结论)
- 在生产中运行Java:SRE的观点
- 子矩阵(NOIP2014 普及组第四题)
- day10 java的this关键字
- [Usaco2007 Dec]宝石手镯[01背包][水]
- 190611每日一句
- 面试:list集合去重
- linux php muma,php实现Linux服务器木马排查及加固功能
- PART 1:基于大数据人才岗位招聘情况对数据进行清洗、初步分析
- R485集线器定协议有多少种能否抗干扰?
- Git超详解七 储藏 (看不懂算我输)
- Android MQTT TLS/SSL 认证
- 基于HFSS的圆形左旋圆极化贴片天线仿真分析
热门文章
- 从1.5k到18k, 一个程序员的5年成长之路【转载】
- 红衣大炮的飞秋实现原理
- 飞鸽传书 v2.51 Build 320 多国语言版
- 控件安全注册方法3选
- 【第2波】有些话,适合在朋友圈说
- 计算机组成原理 微指令编码_计算机组成原理(指令)
- pdf转word python_Python实现PDF转Word
- 苹果小圆点怎么弄出来_原来苹果手机轻点2下屏幕就能截图,以前还不知道,太方便了...
- Windows10系统下虚拟环境的安装与使用
- 别人运行的好好的R代码,到我这怎么就冲突了?