数据结构的学习_4.2 矩阵的压缩存储(对称矩阵)
4.2 矩阵的压缩存储(一)
在有些情况下,矩阵中含有许多值相同或者值为零的元素,如果还按前面的方法来存储这种矩阵,就会产生大量的空间浪费。为了节省存储空间,可以对这类矩阵采用压缩存储。
4.2.1 特殊矩阵
所谓特殊矩阵,指的是相同值的元素或者零元素在矩阵中的分布有一定规律的矩阵。
1.对称矩阵
若n阶方阵A中的元素满足下述性质:
a i j = a j i ( 0 ≤ i , j ≤ n − 1 ) a_{ij}=a_{ji} (0≤i,j≤n-1) aij=aji(0≤i,j≤n−1)
则称A为n阶的对称矩阵。对称矩阵中的元素是关于主对角线对称的,所以只需要存储矩阵上三角或者下三角的元素即可。让两个对称的元素共享一个存储空间。这样,就能够节省近一半的存储空间。
原来数据结构这么厉害,怪不得必须得学。。。
[ a 00 a 10 a 11 a 20 a 21 a 22 . . . . . . . . . a n − 10 a n − 11 . . . a n − 1 n − 1 ] \begin{bmatrix} a_{00}&&&&\\ a_{10}&a_{11}\\ a_{20}&a_{21}&a_{22}\\ ...&...&...&\\ a_{n-10}&a_{n-11}&...&a_{n-1n-1}\\ \end{bmatrix} ⎣⎢⎢⎢⎢⎡a00a10a20...an−10a11a21...an−11a22......an−1n−1⎦⎥⎥⎥⎥⎤
对称矩阵下三角元素示意图
在以上的下三角矩阵中,第i行(0≤i≤m-1)恰好有i+1个元素,所以元素总数为
∑ i = 0 n − 1 ( i + 1 ) = n ( n + 1 ) / 2 \sum_{i=0}^{n-1}(i+1)=n(n+1)/2 i=0∑n−1(i+1)=n(n+1)/2
刚看到
n(n+1)/2
这个公式的时候有点熟,好像在哪里见过。百度了下,就是当年1+2+3+…+100=?这个题所使用的公式吗!!100个100+1然后再除以2。。。
这样看就明白了,原谅我还是没把这思维带入到里面。。。
假设以一维数组sa[n(n+1)/2]作为n阶对称矩阵A的存储结构,那么,矩阵中元素
a i j a_{ij} aij
和数组元素sa[k]之间存在着一 一对应关系。
这个下标ij不好表示到一行中,如果有比较好的工具麻烦跟我说下。
这种对应关系分析如下:
-
若i≥j时,则
a _ {ij}
在下三角矩阵中。a _{ij}
之前i行(从0行到第i-1行)一共有1+2+3+...+i=i * (i+1) /2
个元素,在第i行上,a _{ij}
之前恰好有j个元素。
k = i ∗ ( i + 1 ) / 2 + j ( 0 ≤ k < n ( n + 1 ) / 2 ) k=i * (i + 1) / 2 + j \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ( 0≤ k <n (n+1) / 2 ) k=i∗(i+1)/2+j (0≤k<n(n+1)/2)
-
若i<j时,则
a_{ij}
在上三角矩阵中。因为有
a i j = a j i a_{ij}=a_{ji} aij=aji
所以只要交换i和j即可得到:
k = j ∗ ( j + 1 ) / 2 + i ( 0 ≤ k < n ( n + 1 ) / 2 ) k=j * (j + 1) / 2 + i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ( 0≤ k <n (n+1) / 2 ) k=j∗(j+1)/2+i (0≤k<n(n+1)/2)
因此,有:
k = { j ∗ ( j + 1 ) 2 + i i < j , i ∗ ( i + 1 ) 2 + j i ≥ j , 0 ≤ k < n ( n + 1 ) / 2 k=\begin{cases} \end{cases}^{i*(i+1)2+j\ \ \ \ \ \ i≥j,}_{j*(j+1)2+i\ \ \ \ \ \ i<j,}0≤k<n (n+1) / 2 k={j∗(j+1)2+i i<j,i∗(i+1)2+j i≥j,0≤k<n(n+1)/2
由此,a_{ij}
的存储地址可用下面的公式计算:
L O C ( a i j ) = L O C ( s a [ k ] ) = L O C ( s a [ 0 ] ) + k ∗ d LOC(a_{ij})=LOC(sa[k])=LOC(sa[0])+k*d LOC(aij)=LOC(sa[k])=LOC(sa[0])+k∗d
LOC代表的含义是存储地址,sa[0]是第一个元素,k代表元素个数,d代表一个元素需要d个存储单元
有了上述的计算公式,就能够立即找到矩阵元素a_{ij}
在其压缩存储表示sa中的对应位置k。例如,
a 32 和 a 23 a_{32}和a_{23} a32和a23
都存储在sa[8]中,这是因为
k = i ∗ ( i + 1 ) / 2 + j = 3 ∗ ( 3 + 1 ) / 2 + 2 = 8 k=i*(i+1)/2+j=3*(3+1)/2+2=8 k=i∗(i+1)/2+j=3∗(3+1)/2+2=8
例4.3
已知A和B是两个n * n阶的对称矩阵,因为是对称矩阵,所以仅需要输入下三角元素值存入一维数组。试写一算法,求对称矩阵A和B的乘积。
-
分析:
如果是两个完整的矩阵相乘,其算法是比较简单的,但由于是对称矩阵,所以要清楚对称矩阵的第i行和第j列的元素数据在一维数组中的位置,其位置计算公式为:
l = i ∗ ( i + 1 ) / 2 + j 当 i ≥ j 时 ( A i j , B i j 处 于 下 三 角 中 ) ; l=i*(i+1)/2 +j \ \ \ \ \ \ 当i≥j时(A_{ij},B_{ij}处于下三角中); l=i∗(i+1)/2+j 当i≥j时(Aij,Bij处于下三角中);l = j ∗ ( j + 1 ) / 2 + i 当 i < j 时 ( A i j , B i j 处 于 上 三 角 中 ) ; l=j*(j+1)/2 +i \ \ \ \ \ \ 当i<j时(A_{ij},B_{ij}处于上三角中); l=j∗(j+1)/2+i 当i<j时(Aij,Bij处于上三角中);
期中,l代表
A_{ij}
或B_{ij}
在其对称矩阵中的位置,而且0≤l<n(n+1)/2
。因此,实现本题功能的算法如下:void matrixmult(int a[] ,int b[] ,int c[][20],int n){ //n为A、B矩阵下三角元素个数,a,b分别为一维数组,存放矩阵A和B的下三角元素值 //c存放A和B的乘积 for(i=0;i<20;i++){ for(j=0;j<20;j++){ s=0; for(k=0;k<n;k++){ if(i>=k){ //表示元素为下三角的元素,计算在a数组中的下标 l1=i*(i+1)/2+k; }else { //表示元素为上三角的元素,计算下标 l1=k*(k+1)/2+i; } if(k>=j){ //表示元素为下三角的元素,计算在b数组中的下标 l2=k*(k+1)/2+j; }else { l2=j*(j+1)/2+k; } s=s+a[l1]*b[l2]; } c[i,j]=s; } } }
这例子是啥呀,看都看不懂。心态炸裂。无能狂怒。n代表一个矩阵下三角元素个数?假设20的对阶,个数是20 * (20 +1)/2=210 一半的话也有100多,这循环?????
不敢否认这书的正确性,毕竟是自考指定教材。敢不敢再写详细点。。。。。
算了,略过这个。考试要是考了当我送给你的。
好气啊 。 。。 。。。。。 。。。。。。。。 。。。。。。。。。。。。 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
更多推荐
所有评论(0)