数据结构组广义表
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例如:
M=
0 12 9 0 -3 0 0 0 0 0
0 0 0 0
0 0
0 0
0 0 0 0
Fra Baidu bibliotek
0 14 0 0
0 24
0 18
15 0
0
0
0
-7
0
0
0
0
0
0 i j 2 3 1 6 3 2 1 4 e 12 9 -3 14 24 18 15 -7
矩阵M可表示为:
(TSMatrix M)
M.data: M.mu=6 M.nu=7 M.tu=8
2. 稀疏矩阵
何谓稀疏矩阵?
假设 m 行 n 列的矩阵含 t 个非零元素,则称
mt n
为稀疏因子。 通常认为 0.05 的矩阵为稀疏矩阵。
非零元在矩阵中随机出现。
例如:
M=
0 12 9
0
0
0
0
0
-3 0
0
0
0
0
0
0 0
0
0
0
0 0
0 14 0 0
0 24
0 18
15 0
0
0
0
-7
1 1 3 3 4 5 6 6
三元组顺序表表示的稀疏矩阵的转置运算。
转置是矩阵中最简单的一种运算。对于一个mn的 矩阵A,它的转置矩阵B是一个nm的矩阵,且 B[i][j]=A[j][i],1≤i≤n,1≤j≤m。
0 14 0 0 5 0 7 0 0 0 36 0 0 28 0
基本操作:
InitArray(&A, n, bound1, ..., boundn)
DestroyArray(&A) Value(A, &e, index1, ..., indexn) Assign(&A, e, index1, ..., indexn)
InitArray(&A, n, bound1, ..., boundn) 操作结果:若维数 n 和各维长度合法, 则构造相应的数组A,并 返回OK。
2.二维数组
二维数组可以看成是向量的推广。例如,设A是 一个有m行n列的二维数组,则A可以表示为:
a00 a10
A= …… a0n-1 …… a1n-1 ………………………….
……
a01 a11
am-1 0 am-1 1
am-1 n-1
在此,可以将二维数组A看成是由 m个行向量 [X0, X1, …,Xm-1]T组成,其中,Xi=( ai0, ai1, ….,ain-1), 0≤i≤m-1;也可以将二维数组A看成是由n个列向量[Y0, Y1, ……,Yn-1]组成,其中 Yj=(a0j, a1j, …..,am-1j), 0≤j≤n-1。由此可知二维数组中的每一个元素最多可 有两个直接前驱和两个直接后继(边界除外)。
的存储位置是其下标的线性函数。
以“列序为主序”的存储映象
例如: 二维数组Am×n
a0,0 a1,0 … am-1,0 … … a0,n-1 a1, n-1 … am-1,n-1
L
按列号从小到大的顺序,先将第一列中元素全部存 放完,再存放第二列元素,第三列元素,依次类推……
二维数组A中任一元素ai,j 的存储位置 LOC(i,j) = LOC(0,0) + (m×j+i)×L
(1)按照A的列序进行转置
由于A的列即为B的行,在a.data中,按列扫描, 同一列的元素必按行序递增,因此得到的b.data必按 行优先存放。但为了找到A的每一列中所有的非零元素 ,每次都必须从头到尾扫描A的三元组表(有多少列, 则扫描多少遍)。
例如:
1 1 2 3 3
2 5 2 1 4
14 -5 -7 36 28
3.多维数组
同理,三维数组最多可有三个直接前驱和三个直 接后继,三维以上数组可以作类似分析。可以把三维 以上的数组称为多维数组,多维数组可有多个直接前 驱和多个直接后继。
二. 多维数组在计算机内的存放
高级语言对数组的存储都是采取顺序存储的方 式,由于计算机内存结构是一维的(线性的),因 此,用一维内存存放多维数组就必须按某种次序将 数组元素排成一个线性序列,然后将这个线性序列 顺序存放在存储器中,具体实现方法在下面介绍。
0 0 36 14 7 0 0 0 0 0 0 28 5 0 0
在三元组表表示的稀疏矩阵中,怎样 求得它的转置呢?
从转置的性质知道,将A转置为B,就是将A的三元组 表a.data变为B的三元组表b.data,这时可以将a.data中 i和j的值互换,则得到的b.data是一个按列序为主序排 列的三元组表,再将它的顺序适当调整,变成行序为主 序排列,即得到转置矩阵B。下面将用两种方法处理:
(数组)提要
5.1.1 数组的类型定义 5.1.2 数组的顺序表示和实现
5.1.3 矩阵的压缩存储
ADT Array { 数据对象: D={aj1,j2, ..., jn| ji =0,...,bi -1, i=1,2,..,n (n>0), aj1,j2, ..., jn ∈ElemSet}
数据关系:
} }// transposeSMatrix 算法的时间复杂度:O(nu×tu)
用常规的二维数组表示时的算法:
for (col=1; col<=nu; ++col) for (row=1; row<=mu; ++row) T[col][row] = M[row][col];
其时间复杂度为: O(mu×nu)
二维数组的定义:
数据对象:
D = {aij | 0≤i≤b1-1, 0 ≤j≤b2-1, aij∈ElemSet} 数据关系:
R = { ROW, COL }
ROW = {<ai,j,ai+1,j>| 0≤i≤b1-2, 0≤j≤b2-1} COL = {<ai,j,ai,j+1>| 0≤i≤b1-1, 0≤ j≤b2-2}
a21 a22 … a2n
……
an1 an2 … ann
以对称矩阵为例,n阶对称矩阵A满足: aij=aji 1≤i,j≤n 可为每一对对称元分配一个存储空间。若 以行序为主序存储其下三角中的元,以一维数 组s[n(n+1)/2]作为其存储结构,则s[k]和矩阵元 aij之间的对应关系为:
i(i-1)/2+j-1 k= j(j-1)/2+i-1 (i< j) (i≥ j)
推广到一般情况,可得到 n 维数 组数据元素存储位置的映象关系:
LOC(j1, j2, ..., jn ) = LOC(0,0,...,0) + ∑ c j i i i =1
其中 cn = L,ci-1 = bi ×ci , 1 < i n。
见教材P.93
n
称为 n 维数组的映象函数。数组元素
{q=1;
for ( col=1; col<=M.nu; ++col)
//按列号扫描
for( p=1; p<=M.tu; ++p) //对三元组扫描 if (M.data[p].j= =col) //进行转置 { T.data[q].j=M.data[p].i; T.data[q].i=M.data[p].j; T.data[q].e=M.data[p].e; ++q; }
5.1.1 数组的类型定义
R={R1, R2, ..., Rn} Ri={<aj1,... ji,... jn , aj1, ...ji +1, ...jn > | 0 jk bk -1, 1 k n 且k i, 0 ji bi -2, i=2,...,n }
基本操作:
} ADT Array
以“行序为主序”的存储映象
例如: 二维数组Am×n
a0,0 a0,1 … a0,n-1 … … am-1,0 am-1,1 … am-1,n-1
L
按行号从小到大的顺序,先将第一行中元素全部存 放完,再存放第二行元素,第三行元素,依次类推……
二维数组A中任一元素ai,j 的存储位置 LOC(i,j) = LOC(0,0) + (n×i+j)×L
0
0
0
0
0
0
以常规方法,即以二维数组表示高阶 的稀疏矩阵时会产生的问题:
1) 零值元素占了很大空间; 2) 计算中进行了很多和零值的运算, 遇除法,还需判别除数是否为零。
解决问题的原则:
1) 尽可能少存或不存零值元素;
2) 尽可能减少没有实际意义的运算; 3) 操作方便。 即:
尽可能快地找到与下标值(i,j)对应的元素, 尽可能快地找到同一行或同一列的非零元素。
称为基地址或基址。
同理,三维数组Al×m×n按行优先存放 的地址计算公式为: LOC(i,j,k)=LOC(0,0,0)+(i×m×n+j×n+k)×L
i 0 j m-1 l-1 n-1
k
行序为主序排列规律:
最左边下标变化最慢,最右边下标变化最 快,右边下标变化一遍,与之相邻的左边下标 才变化一次。
DestroyArray(&A) 操作结果:销毁数组A。
Value(A, &e, index1, ..., indexn)
初始条件:A是n维数组,e为元素变量, 随后是n 个下标值。 操作结果:若各下标不超界,则e赋值为 所指定的A 的元素值,并返 回OK。
Assign(&A, e, index1, ..., indexn) 初始条件:A是n维数组,e为元素变量, 随后是n 个下标值。 操作结果:若下标不超界,则将e的值赋 给所指定的A的元素,并返回 OK。
数组和广义表可以看成是线性表 在以下含义上的扩展: ——表中的数据元素本身也是一个数 据结构。
5.1 数组
数组是大家都已经很熟悉的一种数据类型, 几乎所有高级程序设计语言中都设定了数组类 型。在此,我们仅简单地讨论数组的逻辑结构 及在计算机内的存储方式。
一. 多维数组的概念
1.一维数组
一维数组可以看成是一个线性表或一个向量,它 在计算机内存放在一块连续的存储单元中,适合于随 机查找。这在第2章的线性表的顺序存储结构中已经讨 论。
相比较后可以发现,当非零元的个数tu与mu×nu 同数量级时, transposeSMatrix算法的时间复杂度就 成为O(mu×nu2)了,比不压缩存储时的时间复杂度要 大。因此,该算法仅适于tu<<mu×nu的情况。
(2)按照A的行序进行转置(快速转置)
即按a.data中三元组的次序进行转置,并将转置 后的三元组放入b中恰当的位置。首先,在转置前求出 矩阵A的每一列col(即B中每一行)的第一个非零元转 置后在b.data中的正确位置cpot[col](1≤col≤a.nu), 然后,在对a.data的三元组依次作转置时,只要将三 元组按列号col放置到b.data[cpot[col]]中,之后将 cpot[col]内容加1,以指示第col列的下一个非零元的 正确位置。
5.1.2 数组的顺序表示和实现
由于一旦建立了数组,则结构中的数组元素个数和 元素之间的关系就已确定,即它们的逻辑结构就固定下 来了,不再发生变化;数组一般不作插入或删除操作 。 因此,采用顺序存储结构表示数组是顺理成章的事了。
类型特点:
数组是多维的结构,而存储空间是一维的结构。
有两种顺序映象的方式: 1)以行序为主序(行优先,低下标优先); 2)以列序为主序(列优先,高下标优先)。
为了求得位置向量cpot,要先求出A的每一列中非 零元个数num[col],然后利用下面公式:
稀疏矩阵的压缩存储方法:
一、三元组顺序表 二、行逻辑链接的顺序表
三、 十字链表
一、三元组顺序表
#define MAXSIZE 12500 typedef struct { int i, j; //该非零元的行下标和列下标 ElemType e; // 该非零元的值 } Triple; // 三元组类型 typedef struct { Triple data[MAXSIZE + 1]; //data[0]未用 int mu, nu, tu; } TSMatrix; // 稀疏矩阵类型
基地址或基址。
列序为主序排列规律:
最右边下标变化最慢,最左边下标变化最 快,左边下标变化一遍,与之相邻的右边下标 才变化一次。
5.1.3 矩阵的压缩存储 1. 特殊矩阵 2. 稀疏矩阵
1. 特殊矩阵
——非零元在矩阵中的分布有一定的规律。 例如: 对称矩阵 三角矩阵 对角矩阵
a11 a12 … a1n A=
1 2 2 4 5
3 1 2 3 1
36 14 -7 28 -5
void transposeSMatrix (TSMatrix M, TSMatrix &T) { //采用三元组表存储表示,求稀疏矩阵M的转置矩阵T T.mu=M.nu; T.nu=M.mu; T.tu=M.tu;
if (T.tu)