5.3矩阵乘积(三元组存储结构)
来源:互联网 发布:合理利用网络课件ppt 编辑:程序博客网 时间:2024/06/13 23:00
行逻辑链表的顺序表
为了便于随机存取任意一行的非零元,则需要知道每一行的第一个非零元在三元组表中的位置。为此,可将上节快速转置矩阵中的算法创建的,指示“行”信息的辅助数组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值(代码中会用到)
row1234rpos[row]1235
矩阵M的rpos值
row123rpos[row]134rpos[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矩阵乘积(三元组存储结构)
- 稀疏矩阵的三元组存储结构
- 稀疏矩阵三元组存储
- 利用稀疏矩阵的“三元组表”存储结构,实现两个矩阵的相加。
- 数组与广义表_稀疏矩阵的压缩存储_三元组做存储结构_矩阵转置
- 数组与广义表_稀疏矩阵的压缩存储_三元组做存储结构_矩阵相乘
- 稀疏矩阵三元组存储结构的定义及其有关算法的实现
- 顺序存储结构的三元组稀疏矩阵的乘法运算
- 矩阵相加的算法(存储结构为三元组表)
- 稀疏矩阵的三元组顺序表存储结构表示及实现
- 稀疏矩阵的三元组行逻辑链接的顺序表存储结构表示及实现
- 稀疏矩阵 三元组顺序存储
- 稀疏矩阵的三元组顺序存储
- 稀疏矩阵的三元组存储
- 三元组存储求矩阵和
- 第九周--三元组存储稀疏矩阵
- 稀疏矩阵的三元组存储算法
- 通过三元组用顺序存储方式封装稀疏矩阵
- Redis 内存优化
- SSH的整合总结(Spring为主)
- URLProtocol
- mxnet结构介绍
- 非常实用全面的 C++框架,库类等资源
- 5.3矩阵乘积(三元组存储结构)
- ubuntu16.04下安装sublime text3【待续,问题尚未解决】
- Android自动化测试之Monkey使用
- springmvc4+ mybatis3+ spring 4+ activiti5+
- 解决微信小程序switchTab后tab不刷新
- Retrofit
- ConcurrentHashMap小知识
- ObjectMapper
- spring post乱码和get乱码