存储方式 设矩阵 A 中有 s 个非零元素,若 s 远远小于矩阵元素的总数(即s≤m×n),则称 A 为稀疏矩阵。e=s/(m*n),为矩阵的稀疏因子。有人认为 e≤0.05 时称之为稀疏矩阵。
每一个三元组 (i, j, aij) 唯一确定了矩阵A的一个非零元素。因此,稀疏矩阵可由表示非零元的一系列三元组及其行列数唯一确定。
三元组结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> using namespace std;struct Triple { int row, col; int value; void operator =(Triple &R) { row = R.row; col = R.col; value = R.value; } };
稀疏矩阵类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class SparseMatrix { private : int Rows, Cols, Terms; Triple *smArray; public : SparseMatrix (int Rw, int Cl, int Tm); void Transpose (SparseMatrix &b) ; }; SparseMatrix::SparseMatrix (int Rw, int Cl, int Tm) { Rows = Rw; Cols = Cl; Terms = Tm; smArray = new Triple[Terms]; if (smArray == NULL ) { cout << “存储分配失败!” << endl; exit (1 ); } };
转置算法 一个 m*n 的矩阵 A,它的转置矩阵 B 是一个 n*m 的矩阵,且A[_i_][_j_] = B[_j_][_i_]。即 矩阵 A 的行成为矩阵 B 的列 矩阵 A 的列成为矩阵 B 的行。
在稀疏矩阵的三元组表中,非零矩阵元素按行存放。当行号相同时,按列号递增的顺序存放。
扫描列的转置算法 算法思想:
每次从源矩阵中复制一列到新矩阵中
设矩阵列数为 Cols,对矩阵三元组表扫描Cols 次:
第 k 次扫描找寻所有列号为 k 的项:将其行号变列号、列号变行号,顺次存于转置矩阵三元组表。
代码实现 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void SparseMatrix::Transpose (SparseMatrix &B) { B.Rows = Cols; B.Cols = Rows; B.Terms = Terms; if (Terms == 0 ) return ; int CurrentB = 0 ; int i, k; for (k = 0 ; k < Cols; k++) for (i = 0 ; i < Terms; i++) if (smArray[i].col == k) { B.smArray[CurrentB].row = k; B.smArray[CurrentB].col = smArray[i].row; B.smArray[CurrentB].value = smArray[i].value; CurrentB++; } }
算法缺点:
设矩阵三元组表总共有t项,上述算法代价为O(n*t)
若矩阵有200行,200列,1000个非零元素,总共有200000次处理
快速转置算法 为加速转置速度,建立辅助数组 rowSize 和 rowStart: rowSize记录矩阵转置前各列,即转置矩阵各行非零元素个数; rowStart记录各行非零元素在转置三元组表中开始存放位置。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 void SparseMatrix::FastTranspos (SparseMatrix &B) { int *rowSize = new int [Cols]; int *rowStart = new int [Cols]; B.Rows = Cols; B.Cols = Rows; B.Terms = Terms; if (Terms > 0 ) { int i, j; for (i = 0 ; i < Cols; i++) rowSize[i] = 0 ; for (i = 0 ; i < Terms; i++) rowSize[smArray[i].col]++; rowStart[0 ] = 0 ; for (i = 1 ; i < Cols; i++) rowStart[i] = rowStart[i - 1 ] + rowSize[i - 1 ]; for (i = 0 ; i < Terms; i++) { j = rowStart[smArray[i].col]; B.smArray[j].row = smArray[i].col; B.smArray[j].col = smArray[i].row; B.smArray[j].value = smArray[i].value; rowStart[smArray[i].col]++; } } delete [] rowSize; delete [] rowStart; }
时间复杂性:O(2Cols+2Terms)
当Terms << Rows*Cols时,比一般转置算法快,所以又称为快速转置算法。
在空间复杂性上,该算法多用了两个辅助向量,是以少量空间换取了较快的执行速度。