数据结构-数组和广义表(第六章)的整理笔记,若有错误,欢迎指正。
Link:C语言中的数组
!需要注意的是,本章的数组是作为一种数据结构讨论的,而C/C++中的数组是一种数据类型,前者可以借助后者来存储,像线性表的顺序存储结构(即顺序表)就是借助一维数组这种数据类型来存储的,但二者不能混淆!
数组是具有相同类型的数据元素的有限序列,可以将它看作是线性表的推广。
数组的存储结构
- 在设计数组的存储结构时,通常将数组的所有元素存储到存储器的一块地址连续的内存单元中,即数组特别适合采用顺序存储结构来存储。
一维数组的存储结构
- 对于一维数组
(
a
1
,
a
2
,
.
.
.
,
a
n
)
(a_1,a_2,...,a_n)
(a1,a2,...,an),元素顺序存储到一块地址连续的内存单元中。假设第一个元素
a
1
a_1
a1的存储地址用
L
O
C
(
a
1
)
LOC(a_1)
LOC(a1)表示,每个元素占用k个存储单元,则任一数组元素
a
i
a_i
ai的存储地址
L
O
C
(
a
i
)
LOC(a_i)
LOC(ai)即可由以下公式求出:
L O C ( a i ) = L O C ( a 1 ) + ( i − 1 ) × k ( 2 ≤ i ≤ n ) LOC(a_i)= LOC(a_1)+(i-1)×k\;\;\;(2≤i≤n) LOC(ai)=LOC(a1)+(i−1)×k(2≤i≤n) - 该式说明一维数组中任一元素的存储地址可直接计算得到,即一维数组中的任一元素可直接存取,正因为如此,一维数组具有随机存储特性。
二维数组的存储结构
- 对于一个m行n列的二维数组
A
m
×
n
A_{m×n}
Am×n:
[ a 1 , 1 a 1 , 1 ⋯ a 1 , n a 2 , 1 a 2 , 2 ⋯ a 2 , n ⋮ ⋮ ⋱ ⋮ a m , 1 a m , 2 ⋯ a m , n ] \begin{bmatrix} a_{1,1} & a_{1,1} \;\;\;\cdots\;\;\;a_{1,n}\\ a_{2,1} & a_{2,2} \;\;\;\cdots\;\;\;a_{2,n}\\ \vdots & \vdots \;\;\;\ddots\;\;\;\vdots\\ a_{m,1} & a_{m,2} \;\;\;\cdots\;\;\;a_{m,n}\\ \end{bmatrix} ⎣⎢⎢⎢⎡a1,1a2,1⋮am,1a1,1⋯a1,na2,2⋯a2,n⋮⋱⋮am,2⋯am,n⎦⎥⎥⎥⎤
将 A m × n A_{m×n} Am×n简记为A,A是这样的一维数组: A = ( A 1 , A 2 , . . . , A i , . . . , A m ) A=(A_1,A_2,...,A_i,...,A_m) A=(A1,A2,...,Ai,...,Am)。
其中 A i = ( a i , 1 , a i , 2 , . . . , a i , n ) ( 1 ≤ i ≤ m ) A_i=(a_{i,1},a_{i,2},...,a_{i,n})\;\;\;(1≤i≤m) Ai=(ai,1,ai,2,...,ai,n)(1≤i≤m) - 对于二维数组来说,其存储方式主要有两种,即按行优先存放(或者以行序为主序存放)和按列优先存放(或者以列序为主序存放)。
二维数组按行优先存放
- 即先存储第1行,紧接着存储第2行…依此类推,最后存储第m行。
a 1 , 1 a_{1,1} a1,1 | a 1 , 2 a_{1,2} a1,2 | … | … | … | a 1 , n a_{1,n} a1,n |
---|---|---|---|---|---|
a 2 , 1 a_{2,1} a2,1 | a 2 , 2 a_{2,2} a2,2 | … | … | … | a 2 , n a_{2,n} a2,n |
… | … | … | … | … | … |
a i , 1 a_{i,1} ai,1 | a i , 2 a_{i,2} ai,2 | … | a i , j a_{i,j} ai,j | … | a i , n a_{i,n} ai,n |
… | … | … | … | … | … |
a m , 1 a_{m,1} am,1 | a m , 2 a_{m,2} am,2 | … | … | … | a m , n a_{m,n} am,n |
二维数组按行优先存放为:
a 1 , 1 a_{1,1} a1,1 | a 1 , 2 a_{1,2} a1,2 | … | a 1 , n a_{1,n} a1,n | a 2 , 1 a_{2,1} a2,1 | a 2 , 2 a_{2,2} a2,2 | … | a 2 , n a_{2,n} a2,n | … | a i , 1 a_{i,1} ai,1 | a i , 2 a_{i,2} ai,2 | … | a i , j − 1 a_{i,j-1} ai,j−1 | a i , j a_{i,j} ai,j | … | a i , n a_{i,n} ai,n | … | a m , 1 a_{m,1} am,1 | a m , 2 a_{m,2} am,2 | … | a m , n a_{m,n} am,n |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
第1行 | 第2行 | 第i行 | 第m行 |
- 假设第一个元素
a
1
,
1
a_{1,1}
a1,1的存储地址用
L
O
C
(
a
1
,
1
)
LOC(a_{1,1})
LOC(a1,1)表示,每个元素占用k个存储单元,则该二维数组中的任一元素
a
i
,
j
a_{i,j}
ai,j的存储地址可由下式确定:
L O C ( a i , j ) = L O C ( a 1 , 1 ) + [ ( i − 1 ) × n + ( j − 1 ) × k LOC(a_{i,j})=LOC(a_{1,1})+[(i-1)×n+(j-1)×k LOC(ai,j)=LOC(a1,1)+[(i−1)×n+(j−1)×k - 上式推导的思路是,在内存中元素 a i , j a_{i,j} ai,j前面有 i − 1 i-1 i−1行,每行n个元素,即已存放了 ( i − 1 ) × n (i-1)×n (i−1)×n个元素,占用了 ( i − 1 ) × n × k (i-1)×n×k (i−1)×n×k个内存单元;在第i行中元素 a i , j a_{i,j} ai,j前面有 j − 1 j-1 j−1个元素,即已存放了 j − 1 j-1 j−1个元素,占用了 ( j − 1 ) × k (j-1)×k (j−1)×k个内存单元;该数组是从基地址 L O C ( a 1 , 1 ) LOC(a_{1,1}) LOC(a1,1)开始存放的。所以,元素 a i , j a_{i,j} ai,j的内存地址为上述3个部分之和。
以上讨论假设二维数组的行、列下界为1。在更一般的情况下,假设二维数组的行下界是 c 1 c_1 c1,行上界是 d 1 d_1 d1,列下界是 c 2 c_2 c2,列上界是 d 2 d_2 d2,即数组 A [ c 1 . . d 1 , c 2 . . d 2 ] A[c_1..d_1,c_2..d_2] A[c1..d1,c2..d2],则可将上式改写为:
L O C ( a i , j ) = L O C ( a c 1 , c 2 ) + [ ( i − c 1 ) × ( d 2 − c 2 + 1 ) + ( j − c 2 ) ] × k LOC(a_{i,j})=LOC(a_{c_1,c_2})+[(i-c_1)×(d_2-c_2+1)+(j-c_2)]×k LOC(ai,j)=LOC(ac1,c2)+[(i−c1)×(d2−c2+1)+(j−c2)]×k。
二维数组按列优先存放
- 即先存储第1列,紧接着存储第2列…依此类推,最后存储第n列。
二维数组按列优先存放为:
a 1 , 1 a_{1,1} a1,1 | a 2 , 1 a_{2,1} a2,1 | … | a m , 1 a_{m,1} am,1 | a 1 , 2 a_{1,2} a1,2 | a 2 , 2 a_{2,2} a2,2 | … | a m , 2 a_{m,2} am,2 | … | a 1 , j a_{1,j} a1,j | a 2 , j a_{2,j} a2,j | … | a i − 1 , j a_{i-1,j} ai−1,j | a i , j a_{i,j} ai,j | … | a m , j a_{m,j} am,j | … | a 1 , n a_{1,n} a1,n | a 2 , n a_{2,n} a2,n | … | a m , n a_{m,n} am,n |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
第1列 | 第2列 | 第j列 | 第n列 |
- 假设第一个元素
a
1
,
1
a_{1,1}
a1,1的存储地址用
L
O
C
(
a
1
,
1
)
LOC(a_{1,1})
LOC(a1,1)表示,每个元素占用k个存储单元,则该二维数组中的任一元素
a
i
,
j
a_{i,j}
ai,j的存储地址可由下式确定:
L O C ( a i , j ) = L O C ( a 1 , 1 ) + [ ( j − 1 ) × m + ( i − 1 ) × k LOC(a_{i,j})=LOC(a_{1,1})+[(j-1)×m+(i-1)×k LOC(ai,j)=LOC(a1,1)+[(j−1)×m+(i−1)×k - 上式推导的思路是,在内存中元素 a i , j a_{i,j} ai,j前面有 j − 1 j-1 j−1行,每列m个元素,即已存放了 ( j − 1 ) × m (j-1)×m (j−1)×m个元素,占用了 ( j − 1 ) × m × k (j-1)×m×k (j−1)×m×k个内存单元;在第j列中元素 a i , j a_{i,j} ai,j前面有 i − 1 i-1 i−1个元素,即已存放了 i − 1 i-1 i−1个元素,占用了 ( i − 1 ) × k (i-1)×k (i−1)×k个内存单元;该数组是从基地址 L O C ( a 1 , 1 ) LOC(a_{1,1}) LOC(a1,1)开始存放的。所以,元素 a i , j a_{i,j} ai,j的内存地址为上述3个部分之和。
以上讨论假设二维数组的行、列下界为1。在更一般的情况下,假设二维数组的行下界是 c 1 c_1 c1,行上界是 d 1 d_1 d1,列下界是 c 2 c_2 c2,列上界是 d 2 d_2 d2,即数组 A [ c 1 . . d 1 , c 2 . . d 2 ] A[c_1..d_1,c_2..d_2] A[c1..d1,c2..d2],则可将上式改写为:
L O C ( a i , j ) = L O C ( a c 1 , c 2 ) + [ ( j − c 2 ) × ( d 1 − c 1 + 1 ) + ( i − c 1 ) ] × k LOC(a_{i,j})=LOC(a_{c_1,c_2})+[(j-c_2)×(d_1-c_1+1)+(i-c_1)]×k LOC(ai,j)=LOC(ac1,c2)+[(j−c2)×(d1−c1+1)+(i−c1)]×k。
- 从中可以看出,二维数组无论按行优先存储还是按列优先存放存储,都可以在O(1)的时间内计算出指定下标元素的存储地址,体现出随机存储特性。
特殊矩阵的压缩存储
- 特殊矩阵是指非零元素或零元素的分布有一定规律的矩阵,为了节省存储空间,特别是在高阶矩阵的情况下,可以利用特殊矩阵的规律对它们进行压缩存储,以提高存储空间效率。
- 特殊矩阵的主要形式有对称矩阵、对角矩阵等。它们都是方阵,即行数和列数相同。
对称矩阵的压缩存储
-
若一个n阶方阵A[n][n]中的元素满足 a i , j = a j , i , ( 0 ≤ i , j ≤ n − 1 ) a_{i,j}=a_{j,i},(0≤i,j≤n-1) ai,j=aj,i,(0≤i,j≤n−1),则称其为n阶对称矩阵( symmetric matrix)。
一般情况下,一个n阶方阵的所有元素可以分为3个部分,即主对角部分(含n个元素)、上三角部分和下三角部分,已知一个元素的下标,就可以确定它属于哪个部分。
-
对称矩阵中的元素是按主对角线对称的,即上三角部分和下三角部分中的对应元素相等,因此在存储时可以只存储主对角线加上三角部分的元素,或者主对角线加下三角部分的元素,让对称的两个元素共享一个存储空间。
-
若 a i , j a_{i,j} ai,j是A中主对角线或者下三角部分的元素,有 i ≥ j i≥j i≥j。在以行序为主序的存储方式下不计行下标为i的行,元素 a i , j a_{i,j} ai,j的前面共存储了i-1行(行下标为1~i-1,行下标为1的行有一个元素,行下标为2的行有两个元素,…,行下标为i-1的行有i-1个元素),则i-1行共有 1 + 2 + … + ( i − 1 ) = [ 1 + ( i − 1 ) ] × ( i − 1 ) 2 1+2+…+(i-1)=\frac{[1+(i-1)]×(i-1)}{2} 1+2+…+(i−1)=2[1+(i−1)]×(i−1)个元素;在行下标为i的行中,元素 a i , j a_{i,j} ai,j的前面也存储了j-1个元素。所以元素 a i , j a_{i,j} ai,j的前面共存储了 i × ( i − 1 ) 2 + ( j − 1 ) \frac{i×(i-1)}{2}+(j-1) 2i×(i−1)+(j−1)个元素,而B数组的下标是从0开始的,所以有 k = i × ( i − 1 ) 2 + ( j − 1 ) k=\frac{i×(i-1)}{2}+(j-1) k=2i×(i−1)+(j−1)。
-
若 a i , j a_{i,j} ai,j是A中上三角部分的元素,有 i < j i<j i<j。其值等于 a j , i a_{j,i} aj,i,而元素 a j , i a_{j,i} aj,i属于情况(1),它存放在B中下标为 j × ( j − 1 ) 2 + ( i − 1 ) \frac{j×(j-1)}{2}+(i-1) 2j×(j−1)+(i−1)的位置,所以此时有k= j × ( j − 1 ) 2 + ( i − 1 ) \frac{j×(j-1)}{2}+(i-1) 2j×(j−1)+(i−1)。
对称矩阵的压缩存储(按行优先存放):
行下标为1的行:1个元素 | 行下标为2的行:2个元素 | 行下标为i-1的行:i-1个元素 | 行下标为i的行: a i , j a_{i,j} ai,j前面有j-1个元素 | 行下标为n的行:n个元素 | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a 1 , 1 a_{1,1} a1,1 | a 2 , 1 a_{2,1} a2,1 | a 2 , 2 a_{2,2} a2,2 | … | a i − 1 , 1 a_{i-1,1} ai−1,1 | a i − 1 , 2 a_{i-1,2} ai−1,2 | … | a i − 1 , i − 1 a_{i-1,i-1} ai−1,i−1 | a i , 1 a_{i,1} ai,1 | a i , 2 a_{i,2} ai,2 | … | a i , j − 1 a_{i,j-1} ai,j−1 | a i , j a_{i,j} ai,j | … | a i , i a_{i,i} ai,i | … | a n , 1 a_{n,1} an,1 | … | a n , n a_{n,n} an,n |
b 0 b_0 b0 | b 1 b_1 b1 | b 2 b_2 b2 | … | b k b_k bk | b n ( n + 1 ) 2 − 1 b_{\frac{n(n+1)}{2}-1} b2n(n+1)−1 |
将两种情况合起来,得到k与i、j的关系如下:
k = { i × ( i − 1 ) 2 + ( j − 1 ) i ≥ j ( 下 三 角 区 和 主 对 角 线 元 素 ) j × ( j − 1 ) 2 + ( i − 1 ) i < j ( 上 三 角 区 元 素 a i , j = a j , i ) k=\begin{cases} \frac{i×(i-1)}{2}+(j-1)\;\;\;\;i≥j(下三角区和主对角线元素) \\ \frac{j×(j-1)}{2}+(i-1)\;\;\;\;i<j(上三角区元素a_{i,j}=a_{j,i}) \\ \end{cases} k={2i×(i−1)+(j−1)i≥j(下三角区和主对角线元素)2j×(j−1)+(i−1)i<j(上三角区元素ai,j=aj,i)
- 若 a i , j a_{i,j} ai,j是A中主对角线或者下三角部分的元素,有 i ≥ j i≥j i≥j。在以列序为主序的存储方式下不计列下标为j的列,元素 a i , j a_{i,j} ai,j的前面共存储了j-1列(列下标为1~j-1,列下标为1的列有n个元素,列下标为2的列有n-1个元素,…,列下标为j-1的列有n-j+2个元素),则j-1列共有 n + ( n − 1 ) + . . . ( n − j + 2 ) = ( 2 n − j + 2 ) × ( j − 1 ) 2 n+(n-1)+...(n-j+2)=\frac{(2n-j+2)×(j-1)}{2} n+(n−1)+...(n−j+2)=2(2n−j+2)×(j−1)个元素;在列下标为j的列中,元素 a i , j a_{i,j} ai,j的前面也存储了i-j个元素。所以元素 a i , j a_{i,j} ai,j的前面共存储了 ( 2 n − j + 2 ) × ( j − 1 ) 2 + ( i − j ) \frac{(2n-j+2)×(j-1)}{2}+(i-j) 2(2n−j+2)×(j−1)+(i−j)个元素,而B数组的下标是从0开始的,所以有 k = ( 2 n − j + 2 ) × ( j − 1 ) 2 + ( i − j ) k=\frac{(2n-j+2)×(j-1)}{2}+(i-j) k=2(2n−j+2)×(j−1)+(i−j)。
- 若 a i , j a_{i,j} ai,j是A中上三角部分的元素,有 i < j i<j i<j。其值等于 a j , i a_{j,i} aj,i,而元素 a j , i a_{j,i} aj,i属于情况(1),它存放在B中下标为 ( 2 n − i + 2 ) × ( i − 1 ) 2 + ( j − i ) \frac{(2n-i+2)×(i-1)}{2}+(j-i) 2(2n−i+2)×(i−1)+(j−i)的位置,所以此时有k= ( 2 n − i + 2 ) × ( i − 1 ) 2 + ( j − i ) \frac{(2n-i+2)×(i-1)}{2}+(j-i) 2(2n−i+2)×(i−1)+(j−i)。
对称矩阵的压缩存储(按列优先存放):
列下标为1的列:n个元素 | 列下标为2的列:n-2个元素 | 列下标为j-1的列:n-j+2个元素 | 列下标为j的列: a i , j a_{i,j} ai,j前面有i-j+1个元素 | 列下标为n的列:1个元素 | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a 1 , 1 a_{1,1} a1,1 | a 2 , 1 a_{2,1} a2,1 | a 3 , 1 a_{3,1} a3,1 | … | a n , 1 a_{n,1} an,1 | a 2 , 2 a_{2,2} a2,2 | … | a n , 2 a_{n,2} an,2 | … | a j − 1 , j − 1 a_{j-1,j-1} aj−1,j−1 | … | a n , j − 1 a_{n,j-1} an,j−1 | a j , j a_{j,j} aj,j | … | a i − 1 , j a_{i-1,j} ai−1,j | a i , j a_{i,j} ai,j | … | a n , n a_{n,n} an,n |
b 0 b_0 b0 | b 1 b_1 b1 | b 2 b_2 b2 | … | b k b_k bk | b n ( n + 1 ) 2 − 1 b_{\frac{n(n+1)}{2}-1} b2n(n+1)−1 |
将两种情况合起来,得到k与i、j的关系如下:
k = { ( 2 n − j + 2 ) × ( j − 1 ) 2 + ( i − j ) i ≥ j ( 下 三 角 区 和 主 对 角 线 元 素 ) ( 2 n − i + 2 ) × ( i − 1 ) 2 + ( j − i ) i < j ( 上 三 角 区 元 素 a i , j = a j , i ) k=\begin{cases} \frac{(2n-j+2)×(j-1)}{2}+(i-j)\;\;\;\;i≥j(下三角区和主对角线元素) \\ \frac{(2n-i+2)×(i-1)}{2}+(j-i)\;\;\;\;i<j(上三角区元素a_{i,j}=a_{j,i}) \\ \end{cases} k={2(2n−j+2)×(j−1)+(i−j)i≥j(下三角区和主对角线元素)2(2n−i+2)×(i−1)+(j−i)i<j(上三角区元素ai,j=aj,i)
- 显然,一维数组B中存放的元素个数为 1 + 2 + … + n = n ( n + 1 ) 2 1+2+…+n=\frac{n(n+1)}2 1+2+…+n=2n(n+1)。如果A直接采用个n行n列的二维数组存储,所需要的存储空间为 n 2 n^2 n2个元素,所以这种压缩存储方法几乎节省了一半的存储空间。另外,由于一维数组B具有随机存取特性,所以采用这种压缩存储方法后对称矩阵A仍然具有随机存取特性。
- 归纳起来,在计算A中元素 a i , j a_{i,j} ai,j在B中存储位置k时,首先求出元素 a i , j a_{i,j} ai,j前面共存放多少个元素(设为m个);再看B中存放元素的下标是从0开始还是从1开始(设B的初始下标为s),则k=m+s。
上、下三角矩阵的压缩存储
-
所谓上三角矩阵( upper triangular matrix)是指矩阵的下三角部分中的元素均为常数c的n阶方阵。同样,下三角矩阵( lower triangular matrix)是指矩阵的上三角部分中的元素均为常数c的n阶方阵。
-
对于上三角/下三角矩阵,其压缩存储方法是采用以行序为主序/以列序为主序存储其主对角线加上三角部分的元素,另外用一个元素存储常数c,并将压缩结果存放在一维数组B中。显然,B中元素的个数为 n ( n + 1 ) 2 + 1 \frac{n(n+1)}{2}+1 2n(n+1)+1,即用 B [ 0.. n ( n + 1 ) 2 + 1 ] B[0..\frac{n(n+1)}{2}+1] B[0..2n(n+1)+1]存放A中的元素。
- 若 a i , j a_{i,j} ai,j是A中主对角线或者下三角部分的元素,有 i ≥ j i≥j i≥j。在以行序为主序的存储方式下不计行下标为i的行,元素 a i , j a_{i,j} ai,j的前面共存储了i-1行(行下标为1~i-1,行下标为1的行有一个元素,行下标为2的行有两个元素,…,行下标为i-1的行有i-1个元素),则i-1行共有 1 + 2 + … + ( i − 1 ) = [ 1 + ( i − 1 ) ] × ( i − 1 ) 2 1+2+…+(i-1)=\frac{[1+(i-1)]×(i-1)}{2} 1+2+…+(i−1)=2[1+(i−1)]×(i−1)个元素;在行下标为i的行中,元素 a i , j a_{i,j} ai,j的前面也存储了j-1个元素。所以元素 a i , j a_{i,j} ai,j的前面共存储了 i × ( i − 1 ) 2 + ( j − 1 ) \frac{i×(i-1)}{2}+(j-1) 2i×(i−1)+(j−1)个元素,而B数组的下标是从0开始的,所以有 k = i × ( i − 1 ) 2 + ( j − 1 ) k=\frac{i×(i-1)}{2}+(j-1) k=2i×(i−1)+(j−1)。
- 若 a i , j a_{i,j} ai,j是A中上三角部分的元素,有 i < j i<j i<j。其值为常数c,用B中最后一个位置(即下标为 n ( n + 1 ) 2 \frac{n(n+1)}{2} 2n(n+1)的元素)存放常数c。
下三角矩阵的压缩存储(按行优先存放):
行下标为1的行:1个元素 | 行下标为2的行:2个元素 | 行下标为i-1的行:i-1个元素 | 行下标为i的行: a i , j a_{i,j} ai,j前面有j-1个元素 | 行下标为n的行:n个元素 | 常数 | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a 1 , 1 a_{1,1} a1,1 | a 2 , 1 a_{2,1} a2,1 | a 2 , 2 a_{2,2} a2,2 | … | a i − 1 , 1 a_{i-1,1} ai−1,1 | a i − 1 , 2 a_{i-1,2} ai−1,2 | … | a i − 1 , i − 1 a_{i-1,i-1} ai−1,i−1 | a i , 1 a_{i,1} ai,1 | a i , 2 a_{i,2} ai,2 | … | a i , j − 1 a_{i,j-1} ai,j−1 | a i , j a_{i,j} ai,j | … | a i , i a_{i,i} ai,i | … | a n , 1 a_{n,1} an,1 | … | a n , n a_{n,n} an,n | c |
b 0 b_0 b0 | b 1 b_1 b1 | b 2 b_2 b2 | … | b k b_k bk | b n ( n + 1 ) 2 − 1 b_{\frac{n(n+1)}{2}-1} b2n(n+1)−1 | b n ( n + 1 ) 2 b_{\frac{n(n+1)}{2}} b2n(n+1) |
将两种情况合起来,得到k与i、j的关系如下:
k = { i × ( i − 1 ) 2 + ( j − 1 ) i ≥ j ( 下 三 角 区 和 主 对 角 线 元 素 ) n ( n + 1 ) 2 i < j ( 上 三 角 区 元 素 ) k=\begin{cases} \frac{i×(i-1)}{2}+(j-1)\;\;\;\;i≥j(下三角区和主对角线元素) \\ \frac{n(n+1)}{2}\;\;\;\;i<j(上三角区元素) \\ \end{cases} k={2i×(i−1)+(j−1)i≥j(下三角区和主对角线元素)2n(n+1)i<j(上三角区元素)
- 若 a i , j a_{i,j} ai,j是A中主对角线或者下三角部分的元素,有 i ≥ j i≥j i≥j。在以列序为主序的存储方式下不计列下标为j的列,元素 a i , j a_{i,j} ai,j的前面共存储了j-1列(列下标为1~j-1,列下标为1的列有n个元素,列下标为2的列有n-1个元素,…,列下标为j-1的列有n-j+2个元素),则j-1列共有 n + ( n − 1 ) + . . . ( n − j + 2 ) = ( 2 n − j − 2 ) × ( j − 1 ) 2 n+(n-1)+...(n-j+2)=\frac{(2n-j-2)×(j-1)}{2} n+(n−1)+...(n−j+2)=2(2n−j−2)×(j−1)个元素;在列下标为j的列中,元素 a i , j a_{i,j} ai,j的前面也存储了i-j个元素。所以元素 a i , j a_{i,j} ai,j的前面共存储了 ( 2 n − j − 2 ) × ( j − 1 ) 2 + ( i − j ) \frac{(2n-j-2)×(j-1)}{2}+(i-j) 2(2n−j−2)×(j−1)+(i−j)个元素,而B数组的下标是从0开始的,所以有 k = ( 2 n − j − 2 ) × ( j − 1 ) 2 + ( i − j ) k=\frac{(2n-j-2)×(j-1)}{2}+(i-j) k=2(2n−j−2)×(j−1)+(i−j)。
- 若 a i , j a_{i,j} ai,j是A中上三角部分的元素,有 i < j i<j i<j。其值等于 a j , i a_{j,i} aj,i,而元素 a j , i a_{j,i} aj,i属于情况(1),它存放在B中下标为 ( 2 n − i − 2 ) × ( i − 1 ) 2 + ( j − i ) \frac{(2n-i-2)×(i-1)}{2}+(j-i) 2(2n−i−2)×(i−1)+(j−i)的位置,所以此时有k= ( 2 n − i − 2 ) × ( i − 1 ) 2 + ( j − i ) \frac{(2n-i-2)×(i-1)}{2}+(j-i) 2(2n−i−2)×(i−1)+(j−i)。
下三角矩阵的压缩存储(按列优先存放):
列下标为1的列:n个元素 | 列下标为2的列:n-2个元素 | 列下标为j-1的列:n-j+2个元素 | 列下标为j的列: a i , j a_{i,j} ai,j前面有i-j+1个元素 | 列下标为n的列:1个元素 | 常数 | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a 1 , 1 a_{1,1} a1,1 | a 2 , 1 a_{2,1} a2,1 | a 3 , 1 a_{3,1} a3,1 | … | a n , 1 a_{n,1} an,1 | a 2 , 2 a_{2,2} a2,2 | … | a n , 2 a_{n,2} an,2 | … | a j − 1 , j − 1 a_{j-1,j-1} aj−1,j−1 | … | a n , j − 1 a_{n,j-1} an,j−1 | a j , j a_{j,j} aj,j | … | a i − 1 , j a_{i-1,j} ai−1,j | a i , j a_{i,j} ai,j | … | a n , n a_{n,n} an,n | c |
b 0 b_0 b0 | b 1 b_1 b1 | b 2 b_2 b2 | … | b k b_k bk | b n ( n + 1 ) 2 − 1 b_{\frac{n(n+1)}{2}-1} b2n(n+1)−1 | b n ( n + 1 ) 2 b_{\frac{n(n+1)}{2}} b2n(n+1) |
将两种情况合起来,得到k与i、j的关系如下:
k = { ( 2 n − j + 2 ) × ( j − 1 ) 2 + ( i − j ) i ≥ j ( 下 三 角 区 和 主 对 角 线 元 素 ) b n ( n + 1 ) 2 i < j ( 上 三 角 区 元 素 a i , j = a j , i ) k=\begin{cases} \frac{(2n-j+2)×(j-1)}{2}+(i-j)\;\;\;\;i≥j(下三角区和主对角线元素) \\ b_{\frac{n(n+1)}{2}}\;\;\;\;i<j(上三角区元素a_{i,j}=a_{j,i}) \\ \end{cases} k={2(2n−j+2)×(j−1)+(i−j)i≥j(下三角区和主对角线元素)b2n(n+1)i<j(上三角区元素ai,j=aj,i)
对角矩阵的压缩存储
- 若一个n阶方阵A满足其所有非零元素都集中在以主对角线为中心的带状区域中,则称其为n阶对角矩阵(diagonal matrix)。其主对角线上、下方各有b条非零元素构成的次对角线,称b为矩阵半带宽,(2b+1)为矩阵的带宽。对于半带宽为
b
(
0
≤
b
≤
n
ー
1
2
)
b(0≤b≤\frac{nー1}2)
b(0≤b≤2nー1)的对角矩阵,其
∣
i
−
j
∣
≤
b
|i-j|≤b
∣i−j∣≤b的元素
a
i
,
j
a_{i,j}
ai,j不为零,其余元素为零。
例:三对角矩阵—其 ∣ i − j ∣ ≤ 1 |i-j|≤1 ∣i−j∣≤1的元素 a i , j a_{i,j} ai,j不为零,其余元素为零。
- 对于b=1的三对角矩阵,只存储其非零元素,并存储到一维数组B中,将A的非零元素 a i , j a_{i,j} ai,j存储到B的元素 b k b_k bk中。
行优先存储:
- A中行下标为1的行和行下标为n的行都只有两个非零元素,其余各行有3个非零元素。对于行下标不为1的非零元素 a i , j a_{i,j} ai,j来说,在它前面存储了矩阵的前i-1行元素,这些元素的总数为3(i-1)-1。元素 a i , j a_{i,j} ai,j在行下标为i的行(本行)中分为3种情况:
- 若a是本行中的第1个非零元素,则k=3(i-1)-1=3i-4,此时j=i-1,即k
3i-4=2i-3+(i-1)=2i-3+j。 - 若a是本行中的第2个非零元素,则k=3(i-1)-1+1=3i-3,此时j=i,即k
3i-3=(2i+i)-3=2i+j-3。 - 若a是本行中的第3个非零元素,则k=3(i-1)-1+2=3i-2,此时j=i+1,即k
3i-1=2i-3+(i+1)=2i-3+j。
三对角矩阵的压缩存储(按行优先存放)
行下标为1的行:2个元素 | 行下标为2的行:3个元素 | 行下标为3的行:3个元素 | … | 行下标为n的行:2个元素 | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
a 1 , 1 a_{1,1} a1,1 | a 1 , 2 a_{1,2} a1,2 | a 2 , 1 a_{2,1} a2,1 | a 2 , 2 a_{2,2} a2,2 | a 2 , 3 a_{2,3} a2,3 | a 3 , 2 a_{3,2} a3,2 | … | a i , j a_{i,j} ai,j | … | a n , n − 1 a_{n,n-1} an,n−1 | a n − 1 , n a_{n-1,n} an−1,n | a n , n a_{n,n} an,n |
b 0 b_0 b0 | b 1 b_1 b1 | b 2 b_2 b2 | … | b k b_k bk | b 3 n + 1 b_{3n+1} b3n+1 |
归纳起来有k=2i+j-3。
列优先存储:
- A中列下标为1的列和列下标为n的列都只有两个非零元素,其余各列有3个非零元素。对于列下标不为1的非零元素 a i , j a_{i,j} ai,j来说,在它前面存储了矩阵的前j-1列元素,这些元素的总数为3(j-1)-1。元素 a i , j a_{i,j} ai,j在列下标为j的行(本行)中分为3种情况:
- 若a是本列中的第1个非零元素,则k=3(j-1)-1=3j-4,此时i=j-1,即k
3j-4=2j-3+(j-1)=2j-3+i。 - 若a是本列中的第2个非零元素,则k=3(j-1)-1+1=3j-3,此时i=j,即k
3j-3=(2j+j)-3=2j+i-3。 - 若a是本列中的第3个非零元素,则k=3(j-1)-1+2=3j-2,此时i=j+1,即k
3j-1=2j-3+(j+1)=2j-3+i。
三对角矩阵的压缩存储(按列优先存放)
列下标为1的列:2个元素 | 列下标为2的列:3个元素 | 列下标为3的列:3个元素 | 列下标为j的列: a i , j a_{i,j} ai,j前面有i+2j-3个元素 | … | 列下标为n的列:2个元素 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
a 1 , 1 a_{1,1} a1,1 | a 2 , 1 a_{2,1} a2,1 | a 1 , 2 a_{1,2} a1,2 | a 2 , 2 a_{2,2} a2,2 | a 3 , 2 a_{3,2} a3,2 | a 3 , 2 a_{3,2} a3,2 | … | a i , j a_{i,j} ai,j | … | a n − 1 , n a_{n-1,n} an−1,n | a n , n − 1 a_{n,n-1} an,n−1 | a n , n a_{n,n} an,n |
b 0 b_0 b0 | b 1 b_1 b1 | b 2 b_2 b2 | … | b k b_k bk | b 3 n + 1 b_{3n+1} b3n+1 |
归纳起来有k=i+2j-3。