本文已参与「新人创作礼」活动,一起开启掘金创作之路。
GitHub同步更新(已分类):Data_Structure_And_Algorithm-Review
公众号:URLeisure 的复习仓库 (点击可见公众号二维码)
提示:以下是本篇文章正文内容,下面案例可供参考
特殊矩阵的压缩存储
- 在很多科学工程计算问题中,经常遇到一些特殊的矩阵,这些矩阵的很多值是相同的,有的很多元素是 0,为了节省空间,可以对这类矩阵进行压缩存储。
- 压缩存储:给多个相同的元素分配一个存储空间,元素为 0 的不分配空间。
- 可压缩矩阵:对称矩阵、三角矩阵、对角矩阵、稀疏矩阵等。
特殊矩阵的压缩存储方式
对称矩阵
- 对角矩阵,其元素沿着对角线对称,即 a
ij= aji。
-
因为上三角和下三角是一样的,因此只储存其中的一个。
-
如果用一维数组存储下(上)三角,则只需要 n(n+1)/2(n代表行数,计算参照求等差数列前n项和)个空间。比全部存储需要的n^2^个空间少了很多。
-
在上图中,如果只存储其下三角,就将其按行序存储在一维数组 s[ ] 中(下标从 0 开始),如图。
如何寻找 aij 的存储位置?
- 首先,查看存储 a
ij前,已经存储了多少个元素。
-
s[ ] 数组的下标从零开始,则 a
ij的下标就是 i(i-1)/2 + j - 1。 -
上三角的元素( i < j ),根据对称性,a
ij= aji,可以直接读取下三角中 aji( i , j 颠倒)。 -
因此可得出,按行序存储对称矩阵时,a
ij的下标为:
-
如果用一维数组 s[] 存储(下标从 0 开始),则 aij 的存储下标 k = a
ij前面的元素个数。 -
aij 的存储地址:LOC(a
ij) = LOC(a11) + k × L。
三角矩阵
- 三角矩阵分为下三角矩阵和上三角矩阵,下三角矩阵是指矩阵的下三角有数据,而其余的都是常数 c 或者为 0.
- 三角矩阵存储时,只需要存储其下三角中的元素,最后一个空间存储常数 c 即可。如果常数都是 0,则不需要存储。
如何寻找 aij 的存储位置?
- 下三角矩阵与对称矩阵的下三角寻找方式相同。
- 上三角矩阵,如图。
-
从图可以求出,aij前共有 i - 1行的所有元素 + j - i个元素。
-
由等差数列公式可得 k = {(i - 1)(2n - i +2)} / 2 + j - i。
对角矩阵
- 对角矩阵又称为带状矩阵,是指在n × n的矩阵中非零元素集中在主对角线(红色虚线)及其两侧,共L(奇数)条对角线的带状区域内,称为L对角矩阵,如图。
-
此为5对角矩阵。
-
L对角矩阵的带宽为L,半带宽 d = (L - 1) / 2。
-
当| i - j | > d 时,a
ij= 0,为对角矩阵的带状区域外元素;当 | i - j | ≤ d时,aij≠ 0,为对角矩阵的带状区域内元素。
计算 L 对角矩阵一共有多少个非零元素。
-
如图,将每一行以对角线为中心补零,使每行都达到L个元素。通过等差数列计算得左上角补零个数为 d(d + 1)/2。
-
因此,一共补了 d(d + 1) 个零。所以,带状区域元素个数为 L × n - d(d + 1)。
-
因为 d = (L - 1)/2,所以也可以表达为 ( 2d + 1) × n - d(d + 1)。
对角矩阵的存储方式有两种:
- 按行存储
- 按对角线存储
寻找 aij 的存储位置。
按行存储
-
首先找到 a
ii的存储位置,aii是对角线上的元素,以对角线为中心,左右两侧都是 d 个元素。如图。 -
a
ii的存储位置为 (i - 1)× L + d - d。(除了第一行,每行 L 个元素。第一行没存那 d 个零,要减掉) -
所以,a
ij的存储位置为 (i - 1)× L + j - i。 -
无论 a
ij在 aii左边还是右边,公式都一样。 -
按行序,用一维数组(下标从 0 开始)存储 L 对角矩阵,a
ij的存储位置为:
按对角线存储
- 存储时,仍然采用“掐头去尾”,开头和结尾的 0 不存储。
-
先找 a
i`j的存储位置. -
其之前有 i` + d 行,每行有 n 个元素,其左侧有 j - 1 个元素,因为最前面的 d 个零没有存储。
-
所以,存储位置为(i`+ d)× n + j - 1 - d。
-
其中 i` = i - j 。
aij 的存储位置为:
稀疏矩阵
-
稀疏矩阵是指非零元素个数较少,且分布没有规律可言的矩阵。
-
一般认为非零元素小于 5% 时,属于稀疏矩阵。当然也没有那么绝对,只要非零元素个数远远小于矩阵元素个数,就可以认为是稀疏矩阵。如图。
存储方式:
- 为了节省空间,只需记录每个非零元素的行、列和数值即可,这就是三元存储法,如图。
广义表
-
广义表是线性表的推广,也称为列表。
-
它是 n(n ≥ 0)个表元素组成的有限序列,记作 LS = (a
0, a1, a2, ... , an-1)。 -
LS是表名,a
i是表元素,它可以是表(称为子表),也可以是数据元素(称为原子)。n 为表的长度,n = 0 的广义表为空表。
广义表最常见的操作就是求表头和表尾。
- 表头 GetHead(L):非空广义表的第一个元素,可以是一个单元素,也可以是一个子表。
- 表尾 GetTail(L):删除表头元素后,余下的元素所构成的表。表尾一定是一个表
-
例如,D = (a , (b) , (a, (b,c,d) ) ),表长为 3,表头为 a,表尾为 ( (b) , (a, (b,c,d) ) )。
下期预告:螺旋矩阵的实现