Python描述数据结构之数组和特殊矩阵篇

前言

  本篇章主要介绍数组及特殊矩阵,包括数组的基本概念、数组的存储、对称矩阵、三角矩阵、三对角矩阵及稀疏矩阵四种特殊矩阵的压缩。

1. 基本概念

  数组是由 n ( n ≥ 1 ) n(n \geq 1) n(n1)个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素,每个元素在 n n n个线性关系中的序号称为该元素的下标,下标的取值范围称为数组的维界。
  数组是线性表的推广,一维数组可以视为一个线性表,二维数组可以视为其元素也是定长线性表的线性表,以此类推。数组一旦被定义,它的维数和维界就不再改变。因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作。
  Python中内置的数组是array,但通常使用列表list代替。下面给出列表(没说是数组哦)的一些基本操作:

方法功能
append(x)在列表的末尾添加一个元素 x x x
clear()删除列表中的所有元素
copy()返回列表的副本
count(x)返回列表中元素 x x x的个数
extend(iterable)将列表元素(或任何可迭代的元素)添加到列表的末尾
index(x)返回元素 x x x的第一个索引
insert(index, x)在指定位置 i n d e x index index添加元素 x x x
pop(index)删除指定位置 i n d e x index index的元素,默认删除最后一个并返回
remove(x)删除指定元素 x x x
reverse()反转列表
sort(reverse=False, key=myFunc)对列表进行排序,默认升序,可以通过参数 k e y key key指定排序标准的函数

  在Python中最常用的数组运算函数库是numpy,它是一个扩展程序库,在机器学习中超级常用,这里不再叙述,感兴趣的话可以关注或订阅我的机器学习专栏

2. 存储方式

  由于数组一般不进行插入或删除操作,所以一旦建立了数组,其结构中的数据元素个数和元素之间的关系就不再发生变动,所以数组常采用顺序存储结构来存储数据元素。
  一维就是一个线性表,就不多说了,就说一下子多维数组吧,它有按行优先和按列优先两种映射方式。以二维数组(矩阵)为例,按行优先存储的基本思想就是:先行后列,先存储行号较小的元素,行号相等先存储列号较小的元素。
M = [ a 11 a 12 a 13 a 21 a 22 a 23 ] M=\begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \end{bmatrix} M=[a11a21a12a22a13a23]  对于上述矩阵 M M M,按行优先方式在内存中的存储形式为:

在这里插入图片描述
  元素 a i j a_{ij} aij与在数组中的位置 i n d e x index index对应的关系为
{ i n d e x = ( i − 1 ) ∗ c o l u m n + ( j − 1 ) i = i n d e x / / c o l u m n + 1 , j = i n d e x % c o l u m n + 1 \begin{cases} index=(i-1)*column+(j-1)\\ \\ i=index // column+1,j=index \% column+1\\ \end{cases} index=(i1)column+(j1)i=index//column+1,j=index%column+1

  对于上述矩阵 M M M,按列优先方式在内存中的存储形式为:

在这里插入图片描述
  元素 a i j a_{ij} aij与在数组中的位置 i n d e x index index对应的关系为
{ i n d e x = ( j − 1 ) ∗ r o w + ( i − 1 ) i = i n d e x % r o w + 1 , j = i n d e x / / r o w + 1 \begin{cases} index=(j-1)*row+(i-1)\\ \\ i=index \% row+1,j=index // row+1\\ \end{cases} index=(j1)row+(i1)i=index%row+1,j=index//row+1

3. 特殊矩阵

  特殊矩阵是指具有许多相同元素或零元素,并且这些元素的分布有一定规律性的矩阵。
  压缩存储是指为多个值相同的元素只分配一个存储空间,对零元素不分配存储空间,其目的是节省存储空间。
  特殊矩阵的压缩存储方法是指找出特殊矩阵中值相同的元素的分布规律,把那些呈现规律性分布的、值相同的多个矩阵元素压缩存储到一个存储空间中。

3.1 对称矩阵

M = [ a 11 a 12 … a 1 n a 21 a 22 … a 2 n ⋮ ⋮ ⋱ ⋮ a n 1 a n 2 … a n n ] M=\begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \dots & a_{nn} \end{bmatrix} M=a11a21an1a12a22an2a1na2nann   n n n阶矩阵 M M M中的任意一个元素 a i j a_{ij} aij都有 a i j = a j i ( 1 ≤ i , j ≤ n ) a_{ij}=a_{ji}(1\leq i,j\leq n) aij=aji(1i,jn),则称 n n n阶矩阵 M M M为对称矩阵,其中的元素可以分为上三角区 ( i < j ) (i<j) (i<j)、主对角线 ( i = j ) (i=j) (i=j)和下三角区 ( i > j ) (i>j) (i>j)三个部分。
  对于对称矩阵,我们可以为每一对对称元素分配一个存储空间,则可以将 n 2 n^2 n2个元素压缩存储到 n ( n + 1 ) 2 \frac {n(n+1)} {2} 2n(n+1)个存储空间中。这里用数组 A A A来压缩存储矩阵 M M M的下三角区的元素,当然,这里还包括对角线上的元素。数组 A [ k ] A[k] A[k]与矩阵 M M M中的元素 a i j a_{ij} aij存在着以下一一对应的关系:
k = { i ( i − 1 ) 2 + j − 1 , i ≥ j , 即 下 三 角 区 和 主 对 角 线 j ( j − 1 ) 2 + i − 1 , i < j , 即 上 三 角 区 k=\begin{cases} \frac {i(i-1)} {2} +j-1, & i \geq j,即下三角区和主对角线\\ \\ \frac {j(j-1)} {2} +i-1, & i < j,即上三角区 \end{cases} k=2i(i1)+j1,2j(j1)+i1,ij,线i<j,  对于任意给定的一组下标 ( i , j ) (i,j) (i,j),都可以在数组 A A A中找到矩阵 M M M的元素 a i j a_{ij} aij,同理,对所有的 k = 0 , 1 , 2 , … , n ( n + 1 ) 2 − 1 k=0,1,2,\dots,\frac {n(n+1)} {2}-1 k=0,1,2,,2n(n+1)1,也都可以确定数组 A A A中的元素在矩阵 M M M中的位置 ( i , j ) (i,j) (i,j)

k k k0123 … \dots n ( n + 1 ) 2 − 1 \frac {n(n+1)} {2}-1 2n(n+1)1
a i j a_{ij} aij a 11 a_{11} a11 a 21 a_{21} a21 a 22 a_{22} a22 a 31 a_{31} a31 … \dots a n n a_{nn} ann

  上面的 k k k是这样算的:第1行有1个元素,第2行有两个元素,第三行有三个元素, … \dots ,第 i − 1 i-1 i1行有 i − 1 i-1 i1个元素,第 i i i行有 j − 1 j-1 j1个元素 ( a i 1 , a i 2 , … , a i j − 1 ) (a_{i1},a_{i2},\dots,a_{ij-1}) (ai1,ai2,,aij1),所以 k = 1 + 2 + 3 + ⋯ + ( i − 1 ) + ( j − 1 ) = i ( i − 1 ) 2 + j − 1 k=1+2+3+\dots+(i-1)+(j-1)=\frac {i(i-1)} {2} +j-1 k=1+2+3++(i1)+(j1)=2i(i1)+j1

3.2 三角矩阵

M = [ a 11 a 21 a 22 ⋮ ⋮ ⋱ a n 1 a n 2 … a n n ] M = [ a 11 a 12 … a 1 n a 22 … a 2 n ⋱ ⋮ a n n ] M=\begin{bmatrix} a_{11} & & & \\ a_{21} & a_{22} & & \\ \vdots & \vdots & \ddots & \\ a_{n1} & a_{n2} & \dots & a_{nn} \end{bmatrix} M=\begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ & a_{22} & \dots & a_{2n} \\ & & \ddots & \vdots \\ & & & a_{nn} \end{bmatrix} M=a11a21an1a22an2annM=a11a12a22a1na2nann  下三角矩阵中,上三角区的所有元素均为同一常量;上三角矩阵中,下三角区的所有元素均为同一常量。它们的压缩存储方式同对称矩阵是一样的,不同之处在于存储完下三角区和主对角线上的元素之后,紧接着要存储对角线上方的常量,所以需要 n ( n + 1 ) 2 + 1 \frac {n(n+1)} {2}+1 2n(n+1)+1个存储空间,多了一个常量的存储空间。还以下三角区为例:
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 \geq j,即下三角区和主对角线\\ \\ \frac {n(n+1)} {2}, & i < j,即上三角区 \end{cases} k=2i(i1)+j1,2n(n+1),ij,线i<j,

k k k0123 … \dots n ( n + 1 ) 2 − 1 \frac {n(n+1)} {2}-1 2n(n+1)1 n ( n + 1 ) 2 \frac {n(n+1)} {2} 2n(n+1)
a i j a_{ij} aij a 11 a_{11} a11 a 21 a_{21} a21 a 22 a_{22} a22 a 31 a_{31} a31 … \dots a n n a_{nn} ann c c c

  如果是存储上三角区的元素,数组的下标 k k k可以这样计算:第1行有 n n n个元素,第2行有 n − 1 n-1 n1个元素,第3行有 n − 2 n-2 n2个元素, … \dots ,第 i − 1 i-1 i1行有 n − i + 2 n-i+2 ni+2个元素,第 i i i行有 j − i j-i ji个元素,所以 k = n + ( n − 1 ) + ( n − 1 ) + ⋯ + ( n − i + 2 ) + ( j − i ) = ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i k=n+(n-1)+(n-1)+\dots+(n-i+2)+(j-i)=\frac {(i-1)(2n-i+2)} {2}+j-i k=n+(n1)+(n1)++(ni+2)+(ji)=2(i1)(2ni+2)+ji

3.3 三对角矩阵

M = [ a 11 a 12 a 21 a 22 a 23 a 32 a 33 a 34 ⋱ ⋱ ⋱ a n − 1 n − 2 a n − 1 n − 1 a n − 1 n a n n − 1 a n n ] M=\begin{bmatrix} a_{11} & a_{12} & & & & \\ a_{21} & a_{22} & a_{23} & & & \\ & a_{32} & a_{33} & a_{34} & & \\ & & \ddots & \ddots & \ddots \\ & & & a_{n-1n-2} & a_{n-1n-1} & a_{n-1n} \\ & & & & a_{nn-1} & a_{nn} \end{bmatrix} M=a11a21a12a22a32a23a33a34an1n2an1n1ann1an1nann  对角矩阵也称带状矩阵,对于 n n n阶方阵 M M M中的任一元素 a i j a_{ij} aij,当 ∣ i − j ∣ > 1 |i-j|>1 ij>1时,有 a i j = 0 ( 1 ≤ i , j ≤ n ) a_{ij}=0(1\leq i,j\leq n) aij=0(1i,jn),则称为三对角矩阵。在三对角矩阵中,所有非零元素都集中在以主对角线为中心的3条对角线的区域,其他区域的元素都为0。
  三对角矩阵的压缩存储方式是将3条对角线上的元素按行优先的方式存放在一维数组中,且 a 11 a_{11} a11存放在 A [ 0 ] A[0] A[0]中。矩阵 M M M中3条对角线上的元素 a i j a_{ij} aij与一维数组 B B B中的下标对应关系如下:
k = 2 i + j − 3 k=2i+j-3 k=2i+j3  其中, 1 ≤ i , j ≤ n , ∣ i − j ∣ ≤ 1 1\leq i,j\leq n,|i-j|\leq1 1i,jn,ij1

a 11 a_{11} a11 a 12 a_{12} a12 a 21 a_{21} a21 a 22 a_{22} a22 a 23 a_{23} a23 … \dots a n − 1 n a_{n-1n} an1n a n n − 1 a_{nn-1} ann1 a n n a_{nn} ann

  如果知道三对角矩阵 M M M中的某个元素 a i j a_{ij} aij存放于一维数组 A A A的第 k k k个位置,则可得 i = ⌊ k + 1 3 + 1 ⌋ , j = k − 2 i + 3 i=\lfloor \frac {k+1} {3} + 1\rfloor,j=k-2i+3 i=3k+1+1,j=k2i+3

3.4 稀疏矩阵

M = [ 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 ] M=\begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 3 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 4 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 11 & 0 \\ \end{bmatrix} M=0040000000000000000000000300000000000001100000  在 m × n m\times n m×n的矩阵 M M M中,有 t t t个元素不为0,令 δ = t m × n \delta =\frac {t} {m\times n} δ=m×nt,通常认为 δ ≤ 0.05 \delta \leq0.05 δ0.05,我们就称矩阵 M M M为稀疏矩阵, δ \delta δ称为矩阵 M M M的稀疏因子。
  由于稀疏矩阵的零元素的分布没有规律,所以在压缩存储稀疏矩阵时,我们不仅要存储非零元素的值,还要存储其所在的行和列,即构成了一个三元组 ( i , j , a i j ) (i,j,a_{ij}) (i,j,aij)。将上述矩阵 M M M以行优先的方式存储:

i i i j j j a i j a_{ij} aij
053
204
4711

  矩阵的转置运算,即对于一个 m × n m\times n m×n的矩阵 M M M,其转置矩阵 T T T是一个 n × m n\times m n×m的矩阵,且 T ( i , j ) = M ( j , i ) T(i,j)=M(j,i) T(i,j)=M(j,i),即行和列所在的位置进行互换。
T = [ 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0 0 ] T=\begin{bmatrix} 0 & 0 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 3 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 11 \\ 0 & 0 & 0 & 0 & 0 \\ \end{bmatrix} T=0000030000000000004000000000000000000000000110  转置矩阵 T T T也是个稀疏矩阵,其压缩存储方式为:

i i i j j j a i j a_{ij} aij
024
503
7411

  即行和列交换位置后,再按行优先的方式重新对三元组进行排序。除此之外,稀疏矩阵还可以用十字链表法进行存储,那什么是十字链表呢,这个等介绍到图的存储结构时再说。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏小悠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值