第五章 多维数组与广义表
数据结构第五章 数组与广义表

压缩存储方法:只需要存储下三角 (含对角线)上的元素。可节省一 半空间。
可以使用一维数组Sa[n(n+1)/2]作为n阶对称矩阵A的存 储结构,且约定以行序为主序存储各个元素,则在Sa[k]和矩
阵元素aij之间存在一一对应关系: (下标变换公式)
i(i+1)/2 + j 当i≥j k = j(j+1)/2 + i 当i<j
q = cpot[col];
T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i; T.data[q].e = M.data[p].e; ++cpot[col]; }
分析算法FastTransposeSMatrix的时间 复杂度:
for (col=1; col<=M.nu; ++col) … … for (t=1; t<=M.tu; ++t) … … for (col=2; col<=M.nu; ++col) … … for (p=1; p<=M.tu; ++p) … …
//对当前行中每一个非零元
处
brow=M.data[p].j;
理
if (brow < N.nu ) t = N.rpos[brow+1];
M
else { t = N.tu+1 }
的
for (q=N.rpos[brow]; q< t; ++q) { ccol = N.data[q].j; // 乘积元素在Q中列号
一、三元组顺序表
对于稀疏矩阵,非零元可以用三元组表示, 整个稀疏矩阵可以表示为所有非零元的三元组所 构成的线性表。例如:
《数据结构与算法(C++语言版)》第5章 多维数组与广义表

数 组
• 4.寻址公式的计算 • 下面考虑如何根据一组给定下标求出对应数组元素地址的 问题,这是数组最重要的基本操作,一般用在高级语言的 实现当中。这里只考虑n维数组按行存储的寻址公式的计算。 用秦九韶法变换按行存储公式中的主要部分: • j1d2d3…dn + j2d3…dn +…+jn–1dn + jn • =(j1d2+ j2)d3…dn + j3d4…dn +…+jn–1dn + jn • =((j1d2+ j2)d3+ j3)d4…dn + j4d5…dn +…+jn–1dn + jn • =… • =(…(j1d2+ j2)d3+ j3)d4+j4)d5+…+jn–1)dn+ jn • =(…((0×d1+j1)d2+ j2)d3+ j3) d4+j4)d5+…+jn–1)dn+ jn
数 组
• 1. 一维数组 • 一维数组的每个元素只含一个下标,其实质上是一个线性 表,存储方法与普通线性表的顺序存储方法完全相同,即 将数组元素按它们的逻辑次序存储在一片连续区域内。设 一维数组为A =(a0, a1,…, an–1),则它的元素ai的相对地址为 Loc(ai) = i×c。这里,c表示每个元素占用的存储单元数目。
矩阵的压缩存储
• 矩阵是很多科学与工程计算问题研究的数学对象。在高级 语言程序设计中,常用二维数组来存储矩阵元素,有些程 序语言还提供了各种方便用户使用的矩阵运算。然而,对 于在数值分析中经常出现的一些阶数很高,且矩阵中有许 多值相同的元素或者是零元素的特殊矩阵,不适合用二维 数组来存放,因为这将造成大量存储空间的浪费。为了节 省存储空间,可对这类矩阵进行压缩存储,即为多个值相 同的元素只分配一个存储空间,对零元素不分配空间。
数组和广义表

2.三维及多维数组
三维数组Amnp: 可看成有p个二维数组(m*n)所组成的向量,
每个元素aijk同属于三个向量,每个元素最多有3个直接前趋
和3个直接后继。
推广:多维数组An1n2…nm可看成nm个(m-1)维数组所 构成的向量, 任一元素ai1i2…im都属于m个向量,最多有
பைடு நூலகம்
m个直接前趋和m个直接后继。
a11 a21 …... am1a12 a22 …… am2 … … a1n a2n … amn
第 1列
第 2列
第 n列
(以二维数组Amn为例,且数组采用行优先顺序) LOC(aij)=LOC(a11)+[(i-1)*n+j-1]*d
开始元素的 存储起址
n为列数 d为单个元素 所占单元数
c语言中因数组下标从0开始,因此上面的式子应改为: LOC(aij)=LOC(a00)+(i*n+j)*d 随机存取结构 顺序存储的数组是一个随机存取结构,即只要知道开始元
-3 0 0 2 0
转置
B=
0 0 0 0 1 2
0 0 0
0 0 -3 0 2 0 0 0
A= 0 0 0 1 0
-3 0 0 2 0
转置
2 0 0
B=
0 0 0 0 1 2 0 0 0
i 0 1 2
j 1 3 0
v 2 1 -3
i 0
j 2 0 1 2
v -3 2 1 2
转置后
1 3 3
2
3
2
二、多维数组的运算
对于多维数组,通常只有两种操作: 1. 取值:给定一组下标,存取相应的数据元素; 2. 修改:给定一组下标,修改相应数据元素中的某一个
数据结构:第五章:多维数组、稀疏矩阵和广义表

浙江大学计算机学院 杨枨
数据结构
第五章
A的深度为1 B的深度为1 C的深度为2 D的深度为∞
第 21 页 2020年7月5日
5.3.2 存储结构
通常采用链式结构来进行存储
tag
data/link
next
图 5-8 广义表链式存储结构中的结点结构
➢ tag为标志域 ✓ tag=0,则表示该结点为原子结点 ✓ tag=1,则表示该结点为子表
➢ 反之,我们如果按非零元素在A中的列主序进行转置,得到的就是必是按行主序排列的 转置矩阵。
➢ 转置算法的基本思想是:
✓ 对A的三元组表进行c次扫描(c是A的列数),每次扫描都把A的某一列中的非零元 素按序排好,放入B的三元组表中,就得到了B的一行。
✓ 在每次扫描中,为了找到A的每一列中的每一个非零元素,都必须从头到尾扫描A 的三元组表。
➢ 求广义表的深度 ➢ 求广义表的长度、插入、删除、查找等
浙江大学计算机学院 杨枨
数据结构
第 23 页 2020年7月5日
5.3 小结
介绍:
➢ 多维数组 ➢ 稀疏矩阵
✓ 稀疏矩阵可看作是一种特殊的二维数组, ✓ 稀疏矩阵进行压缩存储,可以有效地节省存储空间 ➢ 广义表 ✓ 广义表是一种复杂的数据结构 ✓ 存储表示方法。
浙江大学计算机学院 杨枨
数据结构
第 17 页 2020年7月5日
5.2.2 稀疏矩阵的转置运算
第五章
用三元组顺序表表示的稀疏矩阵的转置运算
➢ 在这个算法中,外层循环用于控制扫描次数,共扫描c次(c是A的列数),每 次扫描都排好B的一行;
➢ 内层循环从头到尾扫描A的三元组表以判断三元组表中的每一个元素是否需要 转置。
数据结构(Java版)-电子教案 第五章 维数组和广义表

例如,二维数组:
A1=( a11 a12 … a1n) A=(A1,A2,…Am)
A2=(a21 a22 … a2n)
… … ……
Amn
Am=(am1 am2 … amn )
a11 a12 .....a 1n a 21 a 22 .....a 2n .......... .......... a m1 a m2 .....a mn
3 4
Ai2 x+10*m x+11*m x+12*m x+13*m x+14*m
Ai3 x+15*m x+16*m x+17*m x+18*m x+19*m
x x+m x+2*m x+3*m x+4*m
址为x
5 6 假设每一个元素占用的存储空间大小为 m,A00的内存地 第二排
5.2 多维数j A1j A2j A3j A4j
1
Ai1 x+m x+5*m x+9*m x+13*m x+17*m
3 4
Ai2 x+2*m x+6*m x+10*m x+14*m x+18*m
Ai3 x+3*m x+7*m x+11*m x+15*m x+19*m
5.1 多维数组
5.1.2 多维数组在计算机内的存放 由于计算机的内存结构是一维的,因此用一维内存来表示 多维数组,就必须按某种次序将数组元素排成一序列,然后 将这个线性序列存放在存储器中。又由于对数组一般不做插 入和删除操作,也就是说,数组一旦建立,结构中的元素个 数和元素间的关系就不再发生变化。因此,一般都是采用顺 序存储的方法来表示数组。
《数据结构——用C语言描述(第二版)》第5章 数组和广义表

第五章 数组和广义表
在压缩存储时,矩阵中值相同的元素C可共享一个存储空间,元素 为零则可不必分配空间,而其余的元素有 n(n+1)/2个,因此三角矩阵 可用一维数组M[n×(n+1)/2+1]来存储,其中常数C放在数组的最后一 个下标变量中。
假设A和B矩阵分别用matrix型指针变量a和b表示,矩阵的转置可以 按以下进行:由于B的行是A的列,所以可按照b->data三元组表的次序在 a->data中找到相应的三元组进行转置,即可按a->data的列序转置,所得 到的转置矩阵B的三元组表b->data必定是按行优先存放的。因此,可以对 三元组表a->data从第一行起扫描,找到A的每一列中所有的非零元素,就 可以实现转置。
LOC ( aij ) =LOC ( a00) +(i×n+j) × c 同理可推导出以列为主序优先存储时数据元素a i j 的存储地址,其计算公式 为:
LOC( a i j ) =LOC( a00 ) +( j × n +i ) × c 对于三维数组Am×n×p而言,若以行为主序优先存储时,则其数据元 素aijk的存储地址可为: LOC ( a i j k) =LOC ( a000) +[ i × m×p +j ×p +k] × c 对于一般的二维数组A[c1…d1,c2…d2]而言,此处c1,c2的值不一定是 0,a i j 的地址为: LOC ( a i j ) =LOC ( a c 1 c 2 ) +[ ( i – c 1 )* ( d 2 – c 2 +1) +j – c 2 ] * c
第五章 数组与广义表

第五章数组、特殊矩阵和广义表本章介绍的数组与广义表可视为线性表的推广,其特点是数据元素仍然是一个表。
本章讨论多维数组的逻辑结构和存储结构、特殊矩阵、矩阵的压缩存储、广义表的逻辑结构和存储结构等。
5.1 多维数组5.1.1 数组的逻辑结构数组是我们很熟悉的一种数据结构,它可以看作线性表的推广。
数组作为一种数据结构其特点是结构中的元素本身可以是具有某种结构的数据,但属于同一数据类型,比如:一维数组可以看作一个线性表,二维数组可以看作“数据元素是一维数组”的一维数组,三维数组可以看作“数据元素是二维数组”的一维数组,依此类推。
图5.1是一个m行n 列的二维数组。
标识,因此,在数组上不能做插入、删除数据元素的操作。
通常在各种高级语言中数组一旦被定义,每一维的大小及上下界都不能改变。
在数组中通常做下面两种操作:(1)取值操作:给定一组下标,读其对应的数据元素。
(2)赋值操作:给定一组下标,存储或修改与其相对应的数据元素。
我们着重研究二维和三维数组,因为它们的应用是广泛的,尤其是二维数组。
5.1.2 数组的内存映象现在来讨论数组在计算机中的存储表示。
通常,数组在内存被映象为向量,即用向量作为数组的一种存储结构,这是因为内存的地址空间是一维的,数组的行列固定后,通过一个映象函数,则可根据数组元素的下标得到它的存储地址。
对于一维数组按下标顺序分配即可。
对多维数组分配时,要把它的元素映象存储在一维存储器中,一般有两种存储方式:一是以行为主序(或先行后列)的顺序存放,如BASIC、PASCAL、COBOL、C等程序设计语言中用的是以行为主的顺序分配,即一行分配完了接着分配下一行。
另一种是以列为主序(先列后行)的顺序存放,如FORTRAN语言中,用的是以列为主序的分配顺序,即一列一列地分配。
以行为主序的分配规律是:最右边的下标先变化,即最右下标从小到大,循环一遍后,右边第二个下标再变,…,从右向左,最后是左下标。
以列为主序分配的规律恰好相反:最左边的下标先变化,即最左下标从小到大,循环一遍后,左边第二个下标再变,…,从左向右,最后是右下标。
多维数组和广义表

an-10, an-11,…,an-1n-1的次序存放在一个含有n(n+1)/2个
元素的向量sa[]中(因下三角元素总数为n(n+1)/2)。即
将aij存放在sa[i(i+1)/2+j]中(0≤i≤n-1,0 ≤j≤i)。
VC++
7
表第 五 章
多 维 数 组 和 广 义
算 法 演
②对称矩阵中的元素aij和sa[k]之间的对应关系: 若i≥j,k=i×(i+1)/2+j 0≤k<n(n+1)/2
页
对于三元组表,除了描述稀疏矩阵的非零元素
外,为了运算方便,还应将矩阵的总行数、总列数
下 一
和非零元素的总数也作为三元组表的属性进行描述。
页 4、三元组表的描述
#define MaxSize 100 //三元组表空间的最大容量
返 typedef int DataType //结点类型
回 typedef struct { //三元组结点定义
和n个直接后继。
下 一
因此,多维数组的逻辑特征是:一个数据元素可能
页 有多个直接前驱和多个直接后继。
三、数组的顺序存储表示
返
由于计算机内存的结构是一维的,因此用内存来
回 表示多维数组,必须将数组元素按某种次序排成线
性序列后存人存储器。又由于数组一般不做插入和
VC++
删除操作,即数组一旦建立,结构中元素个数和元
按行优先顺序元素aij存放在sa[2i+j]中。
10
表第 五 章
多 维 数 组 和 广 义
算 二、稀疏矩阵的压缩存储
法 演
1、稀疏矩阵的定义:设矩阵Amn中有s个非零元素,
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关键问题
如何确定一维数组的大小? = 所需空间
如何确定矩阵元素在一维数组中的位 1 置?从而保证对矩阵元素的随机存取 2
Aij的位置 = 该元素前的元素个数 3 3
12345
4
23456
5
4
34567
5
45678
6
56789
7
…
1 . 对称矩阵
1
1 2 3 4 5 如何确定一维数组的大小? 2
8
9
程序员试题
2019-1 对矩阵压缩存储的主要目的是__(5)__。 (5) A.方便运算 B.节省存储空间
C.降低计算复杂度 D.提高运算速度
2019 将一个三对角矩阵A[l..100,1..100]中的元素按行 存储在一维数组B[l..298]中,矩阵A中的元素A[66,65]在 数组B中的下标为___(4)___。
行指针
029000 0 1^
000000 2
-3 0 0 0 0 4 3 0 0 24 0 0 0 4
5
0 18 0 0 0 0
0 12
2 0 -3 ^ 3 2 24 ^ 4 1 18 ^ 5 0 15 ^
0 29^ 2 54^
5 3 -7 ^
15 0 0 -7 0 0
3.十字链表
i
j Val/Next
a a m-1 0 m-1 1 ……
a m-1 n-1
内存
a0
0 …
a0
n
a1
0
… a1
n
…
假设数组各维的下界是1,按“行优先顺序”存储,假 设每个元素占用d个存储单元。
二维数组Amn, aij的地址计算函数为: LOC(aij)=LOC(a11)+[(i-1)*n+j-1]*d
三维数组Amnp,aijk的地址计算函数为: LOC(aijk)=LOC(a111)+[(i-1)*n*p+(j-1)*p +(k-1)]*d
多维数组
把三维以上的数组称为多维数组, 可有多个直接前驱和多个直接后继 是一种非线性结构。
在C语言中的描述
typedef int datatype;
datatype array1[N];
datatype array2[M][N];
datatype array3[X][Y][Z];
数组一旦被定义,它的维数和维界就不再改 变。因此,数组只有存取元素和修改元素值的 操作。
压缩存储的办法: 只存非零元素。
所需空间:与非零元素的个数和 存储方式有关。
5.2.2 特殊矩阵的压缩存储
矩阵类型 对称矩阵 三角矩阵 对角矩阵
压缩的基本思想:
只存有用的元素 由用二维数组改为用一维数组来存放
说明:
按C语言中规定,下标从0开始 不失一般性,按“行优先顺序”存储
5.2 多维数组的存储
考虑问题的基本出发点:
计算机的内存结构是一维的。因此用一维内存来存多 维数组,就必须按某种次序将数组元素排成线性序列。
数组一旦建立,结构中的元素个数和元素间的关系就 不再发生变化。因此,一般都是采用顺序存储的方法 来表示数组。
两种顺序存储方式
行优先顺序——将数组元素按行排列
32 6
思想一:直接交换a.data中i和j的内容
问题:b.data是一个按列优先顺序存储的稀疏矩阵B
0 2 0 0 Aij=Bji 0 7
056
250
700
060
2.利用三元组表实现转置
120 030 040 006
Aij=Bji
1000 2340 0006
M=4 N=2
i j Aij
T=5
00 1
01 2
11 3
21 4
32 6
M=2 N=4
i j Bij
T=5 0 0 1
01 2
11 3
21 4
23456 34567
N n(n1) 2
3 3 4
4 5 6 7 8 设:存放下三角阵中的元素, 5
5 6 7 8 9 则:如何确定元素Aij在一维 4
数组中的位置?
5
6
i(i1)j 2
当ij,Aij在下三角阵中
Loc(A ) ij
j( j1)i 2
当ij,Aij在上三角阵中 (根据AijAji)
为了节省存储空间, 我们可以对这类矩阵进行压缩 存储。
5.2.1 几种常见的特殊矩阵
对称矩阵
12345 23456
在一个n阶方阵A中,若元素满足下
述性质:aij=aji 0≦i,j≦n-1,则称A 为对称矩阵。
34567 45678 56789
特征:元素关于主对角线对称
压缩存储的办法: 只存矩阵中上三角或下三角中
如何计算数组元素的地址?
按上述两种方式顺序存储的序组,只要知道:
开始结点的存放地址(即基地址), 维数 每维的上、下界 每个数组元素所占用的单元数,
就可以将数组元素的存放地址表示为其下标的线性函 数。因此,数组中的任一元素可以在相同的时间内存 取,即顺序存储的数组是一个随机存取结构。
如何计算数组元素的地址? 内存
最基本的原理
Ai1…in的起始地 址
=
第一个元素 的起始地址
〸
该元素前面 的元素个数
╳
单位 长度
程序员试题
2019-1
对于二维数组a[0…4,1…5],设每个元素占1个存储单
元,且以行为主序存储,则元素a[2,1]相对于数组空
间起始地址的偏移量是___(40)___。
(40)A.5
B.10
C.15
所有的非零元素集中在以主对角线 为中心的带状区域中,
即除了主对角线和主对角线相邻两 侧的若干条对角线上的元素之外, 其余元素皆为零。
压缩存储的办法: 只存对角线上的元素。
存三对角矩阵所需的空间:
N3n2
稀疏矩阵
12005 03000 04000 00600 00080
特征:只有少量非零元素,且非 零元素的分布没有规律。
(6): A.210 (7): A.0 (8): A.Xd+24 (9): A.Xd+29 (10):A.Xd+186
B.240
C.288
B.6
C.94
B.Xd+72 C.Xd+78
B.Xd+77 C.Xd+83
B.Xd+234 C.Xd+270
D.294 D.100
D.Xd+144 D.Xd+147
在PASCAL、C语言中,数组就是按行优先顺序存储的。
列优先顺序——将数组元素按列向量排列
在FORTRAN语言中,数组就是按列优先顺序存储的。
推广到多维数组的情况:
行优先顺序:先排最右下标,从右到左,最后排最左下标 列优先顺序:先排最左下标,从左向右,最后排最右下标。
计算机如何实现数组元素的随机存取?
(4) A.195 B.196 C.197 D.198
5.2.3 稀疏矩阵的压缩存储 顺序存储:三元组表 链式存储:十字链表
1.三元组表存稀疏矩阵
12005
03000 M=5
04000
N=5
T=7
00600
00080
考虑:
只存非零元素
一个非零元素的必需信息有: (i, j, aij)
记录一个稀疏矩阵的必需信息有: 行数M,列数N,非零元素个数T
D.Xd+276
(6)C (7)D (8)B (9)B (10)D
5.2 矩阵的压缩存储
在编程时,简单而又自然的方法,是将矩阵描述为 一个二维数组。矩阵在这种存储表示之下,可以对 其元素进行随机存取。
但是在一些特殊矩阵中,非零元素呈某种规律分布 或者矩阵中有大量的零元素,如果仍用二维数组存, 会造成极大的浪费,尤其是处理高阶矩阵的时候。
D.25
2019
设数组a[3..16,5..20]的元素以列为主序存放,每个元素 占用两个存储单元,则数组元素a[i,j](3≤i≤16,5≤j≤20)的 地址计算公式为___(11)___。
(11)A.a-118+2i+28j
B.a-116+2i+28j
C.a-144+2i+28j
D.a-146+2i+28j
i j Aij 00 1 01 2 04 5 11 3 21 4 32 6 43 8
三元组表的C语言描述
#define maxsize 10000
typedef int datatype; typedef struct{ /*三元组结点*/
i jV
int i,j;
datatype v;
}TriTupleNode;
有一个直接前驱和一个直接后继
二维数组
二维数组可以看成是向量的推广。
有两个直接前驱和两个直接后继
a 00
a 01
……
a 0n-1
a 10
a 11
……
a 1n-1
………………………….
A=
a m -1 0
a m -1 1 … …
a m -1 n-1
三维数组 最多可有三个直接前驱和三个直接后继
的元素。
所需空间:Nn1(i1)n(n1)
i0
2
三角矩阵
12345 03456 00567 00078 00009
12345 43456 44567 44478 44449
10000 23000 36500 47970 58129
14444 23444 36544 47974 58129