稀疏矩阵的转置_稀疏矩阵的快速转置原理及其算法

0f20fca929bdb88c6c3c473f19fb5f4a.png

关于稀疏矩阵的快速转置法,首先得明白其是通过对三元表进行转置。如果误以为是对矩阵进行转置,毫无疑问就算你想破脑袋也想不出个所以然,别陷入死胡同了!

对于一个三元表,行为i,列为j,值为v。需将其i与j的值对调才能得到新的三元表,但是如果直接进行转换,得到的新的三元表的顺序是混乱的,不符合三元表的规则。所以,课本首先介绍了一个用扫描来转置的算法(这个算法比较容易,在这里我就不说了),但是这个转置算法的时间复杂度太高,于是就有了接下来的快速转置算法。

要你对一个三元表进行步骤最少的转置,你可能会想,如果知道三元表中每一项在转置后的新的三元表中的位置,然后直接放进去,岂不是极大的缩小了时间复杂度?没错!快速转置法正是基于这种思想而设计的。

84c44d4de41a819cc6ce0b674cfe3566.png

那么如何知道三元表中某一项的位置呢?在课本98页的a.data这个三元表可以看到,j为列号,在转置后即为新的三元表的行号,三元表正是按照行序进行排列的,而j=1有2个、j=2有2个、j=3有2个、j=4有1个、j=6有1个。根据这些数据按照从小到大排列,j=1的项在新的三元表中应占据第1、2位,j=2的项在新的三元表中应占据第3、4位,j=3的项在新的三元表中应占据第5、6位,j=4应占据第7位,j=6应占据第8位。

接下来就轻松多了,转置的时候直接从第一项读起,读取其j值,比如课本中a.data这个三元表的第一项的j值为2,因为j=2占据第3、4位,所以应该从第三位开始放,接下来如果读取的某一项的j值也是2,就放在第4位。因为j=2的项只有两个,所以第5位绝对不会被j=2的项占据,第5、6项本来就是留给j=3的。再比如当读到j=6的那项时,第8位是留给它的,就可以直接放进第8位了。这样,读取每一项,都能在三元表中找到相应的位置,这就是稀疏矩阵快速转置的原理。

当然,上面只是快速转置的原理,要实现它,就要设计算法来实现了。首先,我们需要两个变量。第一个num[col]用于记录原三元表中列数为col的项的数目,例如col=3时,num[col]=2;第二个cpot[col]用于记录原三元表中列数为col的项在新三元表中的首位置,例如col=3时,cpot[col]=5。你可以打开书本第99页,我想你现在应该是能看懂表5.1了吧。

ab7e9f892052bf1118f6ffe9734c1944.png

接下来说一说快速转置算法的具体事项,在课本的100页代码如下:

8d611f4588ab17e3f6b146d3e18b402f.png

逐句解释:

  • ① 此函数名为FastTransposeSMatrix,形参有原三元表TSMatrix M,作用是传入三元表;三元表TSMatrix &T,采用引用以返回一个三元表。
  • ② 三元表T可能没有初始化,这句的意思是将矩阵M的行数,列数,以及非零元个数传给矩阵T,使其初始化。
  • ③ T.tu为真时,即矩阵M中至少存在一个非零元。
  • ④ 初始化数组num
  • ⑤ 书中的注释是求M中每一列含非零元的个数。具体来说,当原三元表M中某两项或多项的j值相同时,M.data[t].j的值是相等的,因此这个循环完成后,比如说num[3]的值就是原三元表M列数为3的个数。
  • ⑥ 书中的注释标错位置了,应该是第一个for循环的后面。Cpot[1]=1的用处是第一列的在新三元表T的第一个插入位置为1。Cpot[0]是留给储存三元表行列数和非零元个数的。
  • ⑦ 这句话是用来求除第一列外其它每一列的第一个非零元在新三元表T中的位置。第col列第一个非零元的位置为第col-1列第一个非零元的位置加上第col-1列非零元的个数,这是个非常简单的数学问题,没必要多说了。
  • ⑧ M.tu的值是原三元表M的非零元个数,这个循环是用来遍历原三元表M的每一项。
  • ⑨ Col=M.data[p].j的作用是得到循环当前项p的列数值j,赋给col,cpot[col]的值即为第col列的第一个插入位置,如果你问为什么,请看第七句。q=cpot[col]作用是用q来记录当前第col列的插入位置(当然你也可以不用这个赋值,只需把接下来出现的q都改为cpot[col]就行)。
  • ⑩ 将原三元表M的当前第p项的i,j值进行交换后给新三元表T的第q项,这样第p项就转置后正确的插入到新三元表的正确位置。
  • ⑪ 将当前原三元表的第 p 项的非零元的值给新三元表的第 p 项。后一句 ++cpot[col] 这个自增语句是使列数位 col 的项在新三元表的插入位置移动一位,下次再碰到列数位 col 的列时,插入位置即为此次插入位置的下一个。
#include<stdio.h>
#define number 10

typedef struct {
    int i, j;
    int v;
}triple;

typedef struct {
    triple data[10];
    int rows, cols, num;
}TSMatrix;

int FastTransposeSMatrix(TSMatrix M, TSMatrix& T){
    T.rows = M.cols; T.cols = M.rows; T.num = M.num;
    if(T.num){
        for(col=1;col<=M.cols;++col)
            nonzeros[col] = 0;
        for(n=1;n<=M.num;++t)
            ++nonzeros[M.data[n].j];  // 求M中每一列含非零元素个数

        pos[1] = 1;
        for(col=2;col<=M.cols;++col)
            pos[col] = pos[col-1] + nonzeros[col-1];  // 求第col列中第一个非零元素在T.data中的序号

        for(n=1;n<=M.num;++t){
            col = M.data[t].j;
            p = pos[col];
            T.data[p].i = M.data[n].j;
            T.data[p].j = M.data[n].i;
            T.data[p].v = M.data[n].v;
            ++pos[col];
        }  // for

    }  // if

    return 0;
}  // FastTransposeSMatrix

int main() {
    // ...
    // FastTransposeSMatrix(...)...
    return 0;
}

参考

【LB】稀疏矩阵的快速转置原理及其算法_poklau的专栏-CSDN博客​blog.csdn.net
d9bb9d7d7e90736825ecf4c15583f2bf.png
矩阵(稀疏矩阵)的转置算法(C语言)详解​c.biancheng.net
484f980ef9f13d2cdbee78d9368d1022.png
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值