稀疏矩阵是数值计算中普遍存在的一类矩阵,主要特点是绝大部分的矩阵元为零。对于矩阵维度比较小的情况,利用稀疏矩阵特殊性并不能完全发挥优势。然而对于大型矩阵,例如矩阵维度超过10000,那么稀疏矩阵不仅节省存储空间,并且可以让线性代数算法得到极大的加速。比如大部分稀疏矩阵的算法均基于递推方法求解,即主要依赖于矩阵矢量乘法,这样很容易知道利用稀疏性可以优化该类算法的时间复杂度。
稀疏矩阵的存储格式往往依赖具体问题中稀疏矩阵的特征,因此其格式比较多。其中一部分是相对简单而又普遍使用的。例如下面列出的格式,均广泛使用。这篇文章主要介绍每种存储类型实现的基本想法。
CSR(compressed sparse row)
CSR包含三个数组(所有的index从0开始):
- data,用来存储矩阵中的非零元素的值;
- indices,第 i 个元素记录了 data[i] 元素的列数;
- index pointers, 第 i 个元素记录了前 i - 1 行包含的非零元素的数量。
-
对于第 i 行而言,该行中非零元素的列索引为 indices[indptr[i]:indptr[i+1]]
-
根据 indptr[i + 1] - indptr[i],我就得到了该行中的非零元素个数,如:
- 若 indptr[i] = 3 且 indptr[i+1] = 3 ,则第 i 行没有非零元素
- 若 indptr[i] = 6 且 indptr[i+1] = 8, 则第 i 行有两个非零元素,且列索引为 indices[indptr[i]:indptr[i+1]]
-
得到了行索引、列索引,相应的数据存放在: data[indptr[i]:indptr[i+1]]
对于矩阵第 0 行 -
indptr[1] - indptr[0] = 2, 可知第 0 行有 2 个元素。
-
他们的列索引为 indices[0] = 0, indices[1] = 2。
-
存放的元素为 data[0] = 8, data[1] = 2。
-
两个元素对应矩阵中索引分别为 [0, 0], [0, 2]
对于矩阵第 4 行
- indptr[5] - indptr[4] = 6 - 3 = 3, 可知第 4 行有 3 个元素。
- 他们的列索引为 indices[3] = 2, indices[4] = 3, indices[5] = 4。
- 存放的元素为 data[3] = 7, data[4] = 1, data[5] = 2。
- 两个元素对应矩阵中索引分别为 [4, 2], [4, 3], [4, 4]
稀疏矩阵其他的存储方式还有很多,后面会慢慢介绍。