5.1 数组的定义

36
5.1 数数数数数 数数数数数 一、 数数数数数数 数数数数数数数数 数数数数数数 数数数数数数数数数数数数数数 数数数数数数 一,,一。 数数数数数数数数数数数数数数数数数数 数数数数数数数数数数数数 数数数数 数数数数 。,一 数数数 数数数数数数数数数数 数数数数数数数数数数数数数数数 数数数 ,。一 ( j 1 ,j 2 ,…,j n ) 数数数数数数数数数数 0≤j i ≤b i-1 b i 数数数 i 数数数数 ( i=1,2,…, n) 数 n=1 数n 数数数数数数数数数数数数数数数n 数数数数数数数数数数数数数数

Upload: meg

Post on 04-Jan-2016

221 views

Category:

Documents


0 download

DESCRIPTION

5.1 数组的定义. 一、数组的定义  数组可看成是一种特殊的线性表,其特殊在于,线性表中的数据元素本身也是一个数据结构。  数组是由 下标和值 组成的序对的有限集合。数组中每组有定义的下标,都存在一个与其对应的值,这个值称为数组元素。即数组中的每个数据元素都对应一组下标 ( j 1 ,j 2 ,…,j n ) ,每个下标的取值范围是 0≤j i ≤b i-1 , b i 称为第 i 维的长度 ( i=1,2,…,n) 。  当 n=1 时, n 维数组就蜕化为定长的线性表;  反之, n 维数组可以看成是线性表的推广。. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 5.1  数组的定义

5.1 数组的定义5.1 数组的定义

一、数组的定义 数组可看成是一种特殊的线性表,其特殊在于,线性表中的数据元素本身也是一个数据结构。 数组是由下标和值组成的序对的有限集合。数组中每组有定义的下标,都存在一个与其对应的值,这个值称为数组元素。即数组中的每个数据元素都对应一组下标 ( j1,j2,…,jn) ,每个下标的取值范围是 0≤ji≤bi-1 , bi 称为第 i 维的长度 ( i=1,

2,…,n) 。 当 n=1 时, n 维数组就蜕化为定长的线性表; 反之, n 维数组可以看成是线性表的推广。

Page 2: 5.1  数组的定义

例如例如 ,, 对于如下形式的对于如下形式的 m*nm*n 阶矩阵,可以用二维数组表示:阶矩阵,可以用二维数组表示:

二维数组二维数组 AA 还可以看成一个线性表:还可以看成一个线性表:A=(aA=(a

00,a,a11,…,a,…,app) )      (p=m-1(p=m-1 或或 n-1)n-1)

其中,每个数据元素其中,每个数据元素 aajj 是一个列向量形式的线性表:是一个列向量形式的线性表:

aajj=(a=(a0,j0,j,a,a1,j1,j,…,a,…,am-1,jm-1,j) )      (0 ≤j≤n-1)(0 ≤j≤n-1)

或者每个数据元素是一个行向量形式的线性表:或者每个数据元素是一个行向量形式的线性表:aaii=(a=(ai,0i,0,a,ai,1i,1,…,a,…,ai,n-1i,n-1))      (0 ≤i≤m-1)(0 ≤i≤m-1)

AAm×nm×n==

a00 a01 … a0,n-1

a10 a11 … a1,n-1

… … … …

am-1,0 am-1,1 … am-1,n-1

( )

( )

( )

( )(

)

(

)

(

)

(

)

Page 3: 5.1  数组的定义

二、数组的基本操作二、数组的基本操作1. 1. 初始化初始化 InitArray(A,n,bound1,…,boundn )InitArray(A,n,bound1,…,boundn )  如果维数 如果维数 nn 和各维长度合法,则构造相应数组和各维长度合法,则构造相应数组 AA ,并,并且返回且返回 11

2. 2. 销毁销毁 Destroyarray(A) Destroyarray(A)

 销毁已存在的数组 销毁已存在的数组 AA

3. 3. 取值取值 Getarray(A,e,index1,…,indexn)Getarray(A,e,index1,…,indexn)    如果各下标不超界,则 如果各下标不超界,则 ee 被赋值为所指定的被赋值为所指定的 AA 的元素的元素值,并且返回值,并且返回 11

4. 4. 赋值赋值 Assign(A ,e, index1,…,indexn) Assign(A ,e, index1,…,indexn)

 如果各下标不超界,则 如果各下标不超界,则 ee 赋值给所指定的赋值给所指定的 AA 的元素值,的元素值,并且返回并且返回 11

Page 4: 5.1  数组的定义

5.2 5.2 数组的顺序存储结构 数组的顺序存储结构 5.2 5.2 数组的顺序存储结构 数组的顺序存储结构

 由于数组一般不作插入或删除操作,即一旦数组建立,结构中的数据元素个数和元素之间的关系就不再发生变动。因此数组采用顺序结构储存。 对于二维数组可以有两种顺序存储方式:  一种是以行序为主序的存储方式,  另一种是以列序为主序的存储方式。  在 Basic , Pascal , C 等语言中,用的是以行序为主序的存储结构,而在 Fortran 语言中,用的是以列序为主序的存储结构。

Page 5: 5.1  数组的定义

按行序为主序存放按行序为主序存放0

1

n-1

m*n-1

n

Loc( aij )= Loc( a00 ) + ( i×n + j )× L

a00

a01

a0,n-1

a10

a11

a1,n-1

am-1,0

am-1,1

am-1,n-1

a00 a01 … a0,n-1

a10 a11 … a1,n-1

… … … …

am-1,0 am-1,1 … am-1,n-1

2n-1

Page 6: 5.1  数组的定义

按列序为主序存放按列序为主序存放0

1

m-1

m*n-1

m

Loc( aij )= Loc( a00 ) + ( j×m + i )×L

a00

a10

am-1,0

a01

a11

am-1,1

a0,n-1  

a1,n-1

am-1,n-1

a00 a01 … a0,n-1

a10 a11 … a1,n-1

… … … …

am-1,0 am-1,1 … am-1,n-1

2m-1

Page 7: 5.1  数组的定义

例如,假设有二维数组例如,假设有二维数组 A[MA[M ,, N]N] ,设,设 A[0A[0 ,, 0]0] 在在 644644 处,处, AA

[2[2 ,, 2] 2] 在在 676676 处。每个元素占一个存储空间,则处。每个元素占一个存储空间,则 A[4A[4 ,, 5]5] 的的地址地址 为多少?以行序为主序存储。为多少?以行序为主序存储。

同理,可以推出同理,可以推出 nn 维数组的数据元素存储位置的计算公式:维数组的数据元素存储位置的计算公式:Loc( aLoc( aj1,j2,…,jn j1,j2,…,jn )= Loc( a)= Loc( a0,0,…,0 0,0,…,0 ) + (b) + (b22×…×b×…×bnn×j×j1 1 + +

b b33×…×b×…×bnn×j×j2 2 +…+b+…+bnn×j×jn-1n-1 + j + jnn )× L )× L

=Loc( a=Loc( a0,0,…,0 0,0,…,0 )+()+( + j + jn n ) × L) × L

n

ikk

n

ii bj

1

1

1

Loc( aLoc( aij ij )= Loc( a)= Loc( a00 00 ) + ( i×n + j )× L) + ( i×n + j )× L

676=644+(2×n + 2 ) ×1 676=644+(2×n + 2 ) ×1 n=15 n=15

Loc( aLoc( a45 45 )= Loc( a)= Loc( a00 00 ) + ( 4×n + 5 )× 1 = 709) + ( 4×n + 5 )× 1 = 709

Page 8: 5.1  数组的定义

 矩阵是许多科学与工程计算中经常遇到的研究对象。 矩阵是许多科学与工程计算中经常遇到的研究对象。 在某些矩阵中,往往会出现许多值相同的元素或零元素, 在某些矩阵中,往往会出现许多值相同的元素或零元素,为了节省存储空间,可对这类矩阵进行压缩存储。压缩存为了节省存储空间,可对这类矩阵进行压缩存储。压缩存储的原则是:储的原则是:对多个值相同的元素只分配一个存储空间,对多个值相同的元素只分配一个存储空间,对零元不分配空间。对零元不分配空间。 我们把相同的元素或零元素在矩阵中的有一定的规律分 我们把相同的元素或零元素在矩阵中的有一定的规律分布称为布称为特殊矩阵特殊矩阵,如果矩阵中零元素占绝大部分的称为,如果矩阵中零元素占绝大部分的称为稀稀疏矩阵。 疏矩阵。

5.3 5.3 矩阵的压缩存储矩阵的压缩存储 5.3 5.3 矩阵的压缩存储矩阵的压缩存储

Page 9: 5.1  数组的定义

5.3.1 特殊矩阵的压缩存储

一、对称矩阵 在一个 n 阶方阵 A 中,若元素满足下述性质:    aij=aji ,0 i,j n-1,≦ ≦ 则称 A 为对称矩阵。 对称矩阵中的元素关于主对角线对称,故只要存储矩阵中上三角或下三角中的元素,让每两个对称的元素共享一个存储空间,这样,能节约近一半的存储空间。 不失一般性,我们按“行优先顺序”存储主对角线(包括对角线)以下的元素。在这个下三角矩阵中,第 i 行恰有 i+1 个元素,元素总数为: n(n+1)/2.  

Page 10: 5.1  数组的定义

K 0 1 2 3 n(n-1)/2 n(n+1)/2-1

SA[k] a00 a10 a11 a20 an-1,0 an-1,n-1

隐含元素 a01 a02 a0,n-1

 若若 i j≧i j≧ ,则,则 aai ji j 在下三角形中。 在下三角形中。 aai ji j 之前的之前的 ii 行(从第行(从第 00 行到行到第第 i-1i-1 行)一共有行)一共有 1+2+…+i=i(i+1)/21+2+…+i=i(i+1)/2 个元素,在第个元素,在第 i+1i+1 行上, 行上, aai ji j 之前恰有之前恰有 jj 个元素(即个元素(即 aai0i0,a,ai1i1,…,a,…,ai,j-1i,j-1 ),因此有:),因此有:        i(i+1)/2+j 0 k n(n+1)/2-1≦ ≦ 0 k n(n+1)/2-1≦ ≦  若 若 i<ji<j ,则,则 aaijij 是在上三角矩阵中。因为是在上三角矩阵中。因为 aaijij=a=ajiji ,所以只要交,所以只要交换上述对应关系式中的换上述对应关系式中的 ii 和和 jj 即可得到:即可得到:        j(j+1)/2+i 0 k n(n+1)/2-1≦ ≦0 k n(n+1)/2-1≦ ≦

a00 a01 …. … ….. a0,n-1

a10 a11 …….. ……. a1,n-1

an-1,0 an-1,1 …….. an-1,n-1

………………….

Page 11: 5.1  数组的定义

二、三角阵 以主对角线划分,三角矩阵有上三角和下三角两种。上三角矩阵它的下三角(不包括主对角线)中的元素均为常数。下三角矩阵正好相反,它的主对角线上方均为常数。在大多数情况下,三角矩阵常数为零。

a00 0 0 …….. 0

a10 a11 0 …….. 0

an-1,0an-1,1 an-1,2……an-1,n-1

…………………. 0

K 0 1 2 3 … n(n-1)/2 … n(n+1)/2-1

SA[k] a00 a10 a11 a20 … an-1,0 … an-1,n-1

Loc(aij)=Loc(a00)+[i(i+1)/2+j ]*L

Page 12: 5.1  数组的定义

a00 a10 a10 a11…… an-1,n-1

K= 0 1 2 3 3(n-1)

下标与 k 之间对应关系:3i-1 当 i=j+1 时

k= 3i 当 i=j 时 3i+1 当 i=j-1 时

2i+j

三、对角矩阵 如果矩阵中的所有的非零元素都集中在以主对角线为中心的带状区域则称为对角矩阵。 常见的三对角矩阵,可按行的顺序压缩存储。

a00 a01 0 …………… . 0

a10 a11 a12 0 …………… 0

0 0 … an-2,n-3 an-2,n-2 an-2,n-1

0 0 … … an-1,n-2 an-1,n-1

0 a21 a22 a23 0 ……… 0

……………………………

Page 13: 5.1  数组的定义

5.3.2 稀疏矩阵的压缩存储5.3.2 稀疏矩阵的压缩存储

0 8 0 0 4 0 0

0 0 0 0 0 0 0

0 0 0 5 0 0 0

0 0 7 0 0 0 0

2 0 0 0 0 6 0

0 0 9 0 0 0 0

  矩阵中非零元素的个数远远小于矩阵元素的总数,这样的矩阵称为稀疏矩阵。  假设在 m*n 的矩阵中,有 t 个元素不为零,令 δ=t/m*n, 则称 δ 为矩阵的稀疏因子。通常认为 δ≤0.05 时,该矩阵为稀疏矩阵。

Page 14: 5.1  数组的定义

一、三元组表表示法   在存储稀疏矩阵时,为了节省存储单元,很自然地想到使用压缩存储方法。但由于非零元素的分布一般是没有规律的,因此在存储非零元素的同时,还必须同时记下它所在的行和列的位置( i,j) 。  所以一个三元组 (i,j,v) 唯一确定了矩阵 A 的一个非零元。 其中 v 中存放非零元素的数值。因此,稀疏矩阵可由表示非零元的三元组及其行列数唯一确定。  以行优先的顺序将稀疏矩阵中的非零元素以三元组形式存放在一个数组中形成了三元组表。也可把三元组表看成一个线性表,线性表的每个结点对应稀疏矩阵的一个非零元素,这个线性表用顺序的方式存储在连续的存储区。

Page 15: 5.1  数组的定义

   0 8 0 0 4 0 00 8 0 0 4 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 5 0 0 00 0 0 5 0 0 0 0 0 7 0 0 0 00 0 7 0 0 0 0 2 0 0 0 0 6 02 0 0 0 0 6 0 0 0 9 0 0 0 00 0 9 0 0 0 0

A=A=

例如,将矩阵例如,将矩阵 AA 转化为三元组表的形式。转化为三元组表的形式。

转化后的三元组表形式如下:转化后的三元组表形式如下:     ((0,1,8)(0,4,4),(2,3,5),(3,2,7),(4,0,2), ((0,1,8)(0,4,4),(2,3,5),(3,2,7),(4,0,2),         (4,5,6),(5,2,9))(4,5,6),(5,2,9))  加上  加上 (6,7)(6,7) 这一对行、列值便可作为矩阵这一对行、列值便可作为矩阵 AA 的另一种的另一种描述。描述。

Page 16: 5.1  数组的定义

#define Maxsize 255typedef struct{

int i,j;datatype v;

}Triple;

typedef struct{Triple data[Maxsize];int mu,nu,tu;

}TsMatrix;

k i j v

0 0 1 8

1 0 4 4

2 2 3 5

3 3 2 7

4 4 0 2

5 4 5 6

6 5 2 9

稀疏矩阵的三元组表存储表示的定义: 稀疏矩阵的三元组表存储表示的定义:

Page 17: 5.1  数组的定义

void CreatSMatrix(int A1[ ][ ],TsMatrix *A){   int col,row,k;  k=0;  for (row=0;row<m;row++)  for (col=0;col<n;col++)    if (A1[row][col]!=0)    {   A->data[k].i=row;

  A->data[k].j=col;  A->data[k].v=A1[row][col];  k++;

    }  A->mu=m;A->nu=n;A->tu=k;}

算法算法 4.6 4.6 首先我们来建立一个三元组表: 首先我们来建立一个三元组表:

//m,n 为要转换矩阵的行列数,定义为全局变量,在过程中直接使用

Page 18: 5.1  数组的定义

0 8 0 0 4 0 0

0 0 0 0 0 0 0

0 0 0 5 0 0 0

0 0 7 0 0 0 0

2 0 0 0 0 6 0

0 0 9 0 0 0 0

A=

0 0 0 0 2 0

8 0 0 0 0 0

0 0 0 7 0 9

0 0 5 0 0 0

4 0 0 0 0 0

0 0 0 0 6 0

0 0 0 0 0 0

B=

求转置矩阵:求转置矩阵:  转置是一种简单的矩阵运算。对于一个  转置是一种简单的矩阵运算。对于一个 m×nm×n 的矩阵的矩阵AA ,它的转置,它的转置 BB 是一个是一个 n×mn×m 的矩阵,且的矩阵,且 a[i][j]=b[j][i]a[i][j]=b[j][i] ,,0 i m≦≦0 i m≦≦ ,, 0 j n≦ ≦0 j n≦ ≦ ,即,即 AA 的行是的行是 BB 的列,的列, AA 的列是的列是 BB

的行。的行。

// 其时间复杂度为 0 ( nu×mu )

for(col=0;col<n;col++)  for(row=0;row<m;row++)   b[col][row]=a[row][col];

Page 19: 5.1  数组的定义

如何将一个三元组进行转置?  将三元组 A 转置为 B ,就是将 A 的三元组表 a.data 置换为表 B 的三元组表 b.data ,如果只是简单地交换 a.data 中 i

和 j 的内容,那么得到的 b.data 将是一个按列优先顺序存储的稀疏矩阵 B ,要得到按行优先顺序存储的 b.data ,就必须重新排列三元组的顺序。  由于 A 的列是 B 的行,因此,按 a.data 的列序转置,所得到的转置矩阵 B 的三元组表 b.data 必定是按行优先存放的。  按这种方法设计的算法,其基本思想是:对 A 中的每一列 col(0 col n-1)≦ ≦ ,通过从头至尾扫描三元表 a.data ,找出所有列号等于 col 的那些三元组,将它们的行号和列号互换后依次放入 b.data 中,即可得到 B 的按行优先的压缩存储表示。

Page 20: 5.1  数组的定义

M i j v

1 0 1 8

2 0 4 4

3 2 3 5

4 3 2 7

5 4 0 2

6 4 5 6

7 5 2 9

N i j v

1 0 4 2

2 1 0 8

3 2 3 7

4 2 5 9

5 3 2 5

6 4 0 4

7 5 4 6

具体做法:  对矩阵 M 中的每一列 col(0 ~ nu-1) ,扫描所有的非零元素若有一个非零元素的列等于当前列 col ,则将该非零元素行列互换送到目标三元组表。

Page 21: 5.1  数组的定义

void TransposeSMatrix(TsMatrix *a,TsMatrix *b){   int p,q,col;  b->mu=a->nu;   b->nu=a->mu;   b->tu=a->tu;  if (b->tu)  { q=0;   for (col=0;col<a->nu;++col )    for (p=0;p<a->tu;++p )     if (a->data[p].j==col)      { b->data[q].i=a->data[p].j;     b->data[q].j=a->data[p].i;     b->data[q].v=a->data[p].v;++q;      }  }}

算法描述如下: 算法描述如下:

// 扫描 A 的所有列 // 扫描所有非零元

演 示

Page 22: 5.1  数组的定义

怎样才能改进算法的效率呢?

  分析该算法,其时间主要耗费在 col 和 p 的二重循环上,所以时间复杂度为 O(nu*tu) 。和通常存储方式下矩阵转置算法的时间复杂度 O ( mu*nu ),该算法就显得不太理想了,虽然节省了存储空间却提高了时间复杂度。

Page 23: 5.1  数组的定义

  如果能预先确定矩阵 A 中每一列 ( 即 B 中每一行 ) 的第一个非零元的位置,则在对三元组作转置时,就可以直接放到恰当的位置上。  为了确定这些位置,在转置前应首先求得 A 中每一列非零元的个数,进而求得每一列第一个元素在转置后应有的位置。  首先引入了两个辅助向量 num 和 pos ,其中 num[col] 表示矩阵 A 中第 col 列中非零元素的个数, pos[col] 表示 A 中第 col 列的第一个非零元素在转置后的恰当位置。 则有:

pos[0]=0

pos[col]=pos[col-1]+num[col-1] 1≤col≤A.nu-1

col 0 1 2 3 4 5

num[col] 1 1 2 1 1 1

pos[col] 0 1 2 4 5 6

Page 24: 5.1  数组的定义

void FastTransposeSMatrix(TsMatrix *a,TsMatrix *b){

b->mu=a->nu; b->nu=a->mu; b->tu=a->tu;if (b->tu){

for (col=0;col<a->nu;col++ ) num[col]=0;for (t=0;t<a->tu;t++ ) ++num[a->data[t].j];pos[0]=0;for (col=1;col<a->nu;col++ )

pos[col]= pos[col-1]+num[col-1];for (p=0;p<a->tu;p++){

col=a->data[p].j;q= pos[col];b->data[q].i=a->data[p].j;b->data[q].j=a->data[p].i;b->data[q].v=a->data[p].v;++ pos[col];

}}

}O(nu+tu)

// 非零元的列号

Page 25: 5.1  数组的定义

伪地址 值1 8

4 4

17 5

23 7

28 2

33 6

37 9

二、伪地址表示法 所谓伪地址就是元素在矩阵里按行优先(按列优

先)顺序的相对位置(包括零元素一起算)。例如上述矩阵,按行优先顺序非零元的伪地址为:   用伪地址表示,线性表的每个结点包含两个域,一个是非零元素的伪地址,另一个是元素的值。这种方法共需 2*tu( tu 为非零元素个数)个存储单元,比三元组法节省,但要计算伪地址。 m×n 的稀疏矩阵 A 的元素 A[i][j] 的伪地址可用 i*n+j 来计算。

Page 26: 5.1  数组的定义

i j v

down right

非零元素行号

非零元素列号

非零元素的值

向下域 向右域

三、十字链表  在十字链表中,稀疏矩阵的每一行用一个带头结点的循环链表表示,每一列也用一个带表头结点的循环链表表示。在这个结构中,除表头结点外,每一个节点都代表矩阵中的一个非零元素,它由五个域组成:行域,列域,值域,向下域和向右域。节点结构如下:

Page 27: 5.1  数组的定义

十字链表 设行指针数组和列指针数组,分别指向每行、列第一个

非零元 结点定义

tpedef struct node{ int row,col,val; struct node *down, *right;}JD;

row col valdown right

34008

000

450

003

A

1 1 3

4 1 8

2 2 5 2 3 4

^

^ ^

^

^ ^ ^

Page 28: 5.1  数组的定义

5.4 广义表 5.4 广义表 广义表的定义

LS =( a0 , a1 ,…, an-1 ) 其中: LS 是广义表的名称, n 是它的长度。 在线性表中 ai 只限于单个元素。 在广义表中 ai 可以是单个元素也可以是广义表,分别称为广义表 LS 的原子和子表。  当 n=0 时称为广义表 LS 空表。  通常用大写字母 A~Z 表示广义表的名称,用小写字母 a~z表示单个数据元素(原子),广义表用括号括起来,括号内的数据元素用逗号分隔开。   广义表有一定的层次,广义表的深度为它所含括号的重数,所以,空表的深度为 1 ,原子的深度为 0 。

Page 29: 5.1  数组的定义

  当 LS 非空时,称第一个元素 a1 为 LS 的表头 (Head),其余元素组成的表 (a2,a3,…,an) 称 LS 的表尾 (Tail) 。

(1) A=( ) — A 是一个空表,它的长度为 0 。(2) B=(e) — 列表 B 只有一个原子 e ,长度为 1 。(3) C=(a,(b,c,d)) — 列表 C 的长度为 2 ,它的两个元素分   别为原子 a 和子表( b , c , d )。(4) D=(A,B,C) — 列表 D 的长度为 3 ,三个元素都是子表。 显然,若将它子表的值代入后,则有:      D=((),(e),(a,(b , c,d))) 。  它的表头是 () ,表尾是 (B , C) 。(5) E = (a , E) , E 是一个递归表,它的长度为 2 。  它相当于如下的无限列表: E= (a,(a,(a,…))) 。  它的表头是原子 a ,表尾是 (E) 。

Page 30: 5.1  数组的定义

从定义和例子可以得到广义表的下列重要性质:( 1 )广义表是一种多层次的数据结构。广义表的元素可以是

单元素,也可以是子表,而子表的元素还可以是子表。( 2 )广义表可以是递归的表。广义表的定义并没有限制元素

的递归,即广义表也可以是其自身的子表。例如表 E 就是一个递归的表。

( 3 )广义表可以为其他表所共享。例如,表 A、表 B、表 C是表 D 的共享子表。在 D 中可以不必列出子表的值,而用子表的名称来引用。 D

e

b c

a

d

A B C

Page 31: 5.1  数组的定义

定义可知,任何一个非空列表其表头可能是原子,也可能是列表,而其表尾必定为列表。例如:

A=( ) B=(e) C=(a,(b,c,d)) D=(A,B,C)

  Head(B) = e , Tail(B) = ( ) ,  Head(C) = a Tail(C)= ((b, c, d ) )

  Head(D) = A , Tail(D) = (B,C) ,由于 (B,C) 为非空表,可以继续分解:

  Head((B,C))=B, Tail((B,C))=(C),

  Head(E) = a , Tail(E) = (E) 注意:广义表 ( ) 和 (( )) 不同,前者是空表,长度为 n=0 ;后者长度 n=1 ,它有一个元素是空表,可分解得到表头和表尾均是空表 ( ) 。

Page 32: 5.1  数组的定义

例:求下列广义表操作的结果(严题集 5.10②) p33

Page 33: 5.1  数组的定义

5.5 广义表的存储结构结点结构 :  由于广义表中的数据元素有单元素和子表之分,相应地结点的结构形式也有两种:

一种是元素结点,用以表示单元素;一种是子表结点,用以表示列表。

对于单元素结点,应包括元素值域和指向其后继结点的指针域;对于子表结点,应该包括指向子表中第一个结点的表头指针域和指向后继结点的指针域。为了区分这两类结点,在结点中设置一个标志域

如果标志为 0 ,表示该结点为元素结点;如果标志为 1 ,则表示该结点为子表结点。

Page 34: 5.1  数组的定义

enum Boolean{0,1};

struct GLNode

{ Boolean tag; //tag=1 表示有子表union

{ ElemType data; // 单元素的值GLNode * sublist; // 子表的头指针

};

GLNode * next; // 后继结点};

tag=1 sublist next tag=0 data next

子表结点 单元素结点

Page 35: 5.1  数组的定义

A=( ) B=(e) C=(a,(b,c,d)) D=(A,B,C)

Page 36: 5.1  数组的定义

作业:1. 已经顺序表 A 的元素有序递增,顺序表 B 的元素有序递减,写一算法将 B 的所有元素插入到 A 中,并且插入后 A 仍保持原序。(可设 AB 的数据元素类型为整型)

2. 设 A= ( a1,a2,…,an )和 B= ( b1,b2,…,bm )是两个带尾指针的循环链表,写一算法将 B 表链接到 A 表的尾上,即使

A= ( a1,a2,…,an , b1,b2,…,bm )。