二、下面给出另外一种称之为快速转置的算法
按M.data中三元组的次序进行转置,并将转置后的三元组装入T中恰当的位置。其算法思想为:对M扫描一次,按M第二列提供的列号一次确定位置装入T的一个三元组。具体实施如下:一遍扫描先确定三元组的位置关系,二次扫描由位置关系装入三元组。可见,位置关系是此种算法的关键。
为了预先确定矩阵M中的每一列的第一个非零元素在数组B中应有的位置,需要先求得矩阵M中的每一列中非零元素的个数。因为:矩阵M中第一列的第一个非零元素在数组B中应有的位置等于前一列第一个非零元素的位置加上前列非零元素的个数。
为此,需要设置两个一维数组num[0..n]和cpot[0..n]
num[0..n]:统计M中每列非零元素的个数,num[col]的值可以由A的第二列求得。cpot[0..n]:由递推关系得出M中的每列第一个非零元素在B中的位置。
算法通过cpot数组建立位置对应关系:
例如:下面动画演示的矩阵M和相应的三元组A可以求得num[col]和cpot[col]的值如下:
col 1 2 3 4 5 6 7
num[col] 2 2 2 1 0 1 0
cpot[col] 1 3 5 7 8 8 9
求矩阵M的转置矩阵T的动画演示
算法5.2
Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) { // 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵T T.mu=M.nu; T.nu=M.mu; T.tu=M.tu; if (T.tu) { for (col=1; col<=M.nu; ++col) num[col]=0; for (t=1; t<=M.tu; ++t) ++num[M.data[t].j]; // 求M中每一列所含非零元的个数 cpot[1] = 1; for (col=2; col<=M.nu; ++col) cpot[col]=cpot[col-1]+num[col-1]; // 求M中每一列的第一个非零元在b.data中的序号 for (p=1; p<=M.tu; ++p) { // 转置矩阵元素 col=M.data[p].j; q=cpot[col]; T.data[q].i=M.data[p].j; T.data[q].j=M.data[p].i; T.data[q].e=M.data[p].e; ++cpot[col]; } // for } // if return OK; } // FastTransposeSMatrix |
这个算法仅比前一个算法多用了两个辅助向量。从时间上看,算法中有四个并列的单循环,循环次数分别为nu和tu,因而总的时间复杂度为O(nu+tu)。在M的非零元个数tu和mu×nu等数量级时,其时间复杂度为: O(mu*nu),和经典算法的时间复杂度相同。
三元组顺序表又称有序的双下标法,它的特点是,非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算。然而,若需按行号存取某一行的非零元,则需从头开始进行查找。