数据结构-广义表

合集下载

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

数据结构第五章 数组与广义表
an-1,n-1
压缩存储方法:只需要存储下三角 (含对角线)上的元素。可节省一 半空间。
可以使用一维数组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中列号
一、三元组顺序表
对于稀疏矩阵,非零元可以用三元组表示, 整个稀疏矩阵可以表示为所有非零元的三元组所 构成的线性表。例如:

数据结构-广义线性表广义表

数据结构-广义线性表广义表
template <class T> class Lists { public: Lists( ) ; Lists(Lists ls1, Lists ls2); ~Lists( ); int Length( ); int Depth(GLNode<T> *ls); GLNode *Head( ); GLNode *Tail( ); private: GLNode<T> *ls; };
清华大学出版社
数据结构( 数据结构(C++版) 版
广义线性表——广义表 广义线性表——广义表 ——
广义表的示例 AБайду номын сангаас=( ) B =(e) C =(a, (b,c,d)) , , D =(A, B, C) E =(a, E) F =(( ))
长度?深度?表头?表尾? 长度?深度?表头?表尾?
清华大学出版社
数据结构( 数据结构(C++版) 版
广 义 表 类 的 声 明
清华大学出版社
广义线性表——广义表 广义线性表——广义表 ——
数据结构( 数据结构(C++版) 版
广义表的操作——建立广义表 建立广义表 广义表的操作 template <class T> Lists::Lists(Lists ls1,Lists ls2) { ls = new GLNode ls->tag = 1; ls->ptr.hp = ls1; ls->ptr.tp = ls2; }

C
1 0 a
1 1 0 b
1 0 c
1

0 d
清华大学出版社
广义线性表——广义表 广义线性表——广义表 ——

数据结构广义表

数据结构广义表

结点结构是无论什么结点都有三个域:
第一个域是结点类型标志tag; 第二个域是指向一个列表的指针(当tag=1时) 或一个原子(当tag=0时); 第三个域是指向下一个结点的指针tp。
3 广义表的存储结构
形式描述为:
typedef enum{ ATOM, LIST }ElemTag typedef struct GLNode { //定义广义表结点 ElemTage tag; //公共部分,用以区分 原子结点和表结点 Unin{ //原子结点和表结点的联合部分 AtomType atom;//原子类型结点域, // AtomType由用户定义 struct GLNode *hp,; //表结点的表头指针域 }; struct GLNode *tp; //指向下一个结点的指针 }*Glist; //广义表类型
5. E=(a,E)
这是一个递归列表,其元素中有自己。
广义表也可以用图形表示,例如前述的广义表D和E可表示为:
广义表D
D
广义表E
E
C
A
B
a
e
a b c d
2 广义表的基本运算
广义表的基本运算 ⑴ 取表头 HEAD(LS); ⑵ 取表尾 TAIL(LS)。
3 广义表的存储结构
广义表中的数据元素可以是单元素,或是广义表, •很难用顺序存储结构表示,常采用链式存储结构。 1.表头表尾链存储结构 有两类结点:表结点和单元素结点。
P 1 3 1 1
A=y((c,3),(D,2)) C=x((1,10),(2,6))

1 2
A
z y 1 1 1 3
C
x 0 0 15 ^
B
1 2
1 2

《数据结构——用C语言描述(第二版)》第5章 数组和广义表

《数据结构——用C语言描述(第二版)》第5章  数组和广义表
是指矩阵的下三角(不含对角线)中的元素均为常数C或零的n阶矩阵,下 三角矩阵则与之相反,如图5.3所示。
第五章 数组和广义表
在压缩存储时,矩阵中值相同的元素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

数据结构广义表

数据结构广义表

数据结构广义表介绍广义表是一种扩展了线性表的数据结构,可以存储不仅仅是数据元素,还可以存储子表,从而形成多级结构。

在广义表中,元素可以是基本类型(如整数、字符等),也可以是广义表。

广义表由一组元素组成,每个元素可以是一个基本元素或者是一个子表。

广义表可以为空,称为空表。

广义表中的元素的个数称为广义表的长度。

广义表的表示广义表可以通过两种方式进行表示:括号表示和逗号表示。

1.括号表示:使用括号将广义表括起来,每个元素之间使用逗号分隔。

例如,(1,2,3)表示一个包含3个元素的广义表,分别为1、2和3。

2.逗号表示:用逗号将广义表的元素分隔开,如果元素是基本元素,则直接写在逗号之间,如果元素是子表,则将子表表示为广义表的形式。

例如,1,2,3表示一个包含3个元素的广义表,分别为1、2和3。

广义表的操作广义表支持多种操作,包括获取广义表的长度、判断广义表是否为空、获取广义表的头、获取广义表的尾、判断两个广义表是否相等、复制广义表等。

获取广义表的长度获取广义表的长度即求广义表中元素的个数。

可以使用递归的方式来实现这个操作。

如果广义表为空,则长度为0;否则,长度等于广义表头的长度加上广义表尾的长度。

判断广义表是否为空判断广义表是否为空即判断广义表中是否没有元素。

如果广义表长度为0,则为空;否则,不为空。

获取广义表的头获取广义表的头即获取广义表中第一个元素。

如果广义表为空,则没有头;否则,头等于广义表中的第一个元素。

获取广义表的尾获取广义表的尾即获取广义表中除了第一个元素以外的所有元素。

如果广义表为空,则没有尾;否则,尾等于广义表中除了第一个元素以外的所有元素所组成的广义表。

判断两个广义表是否相等判断两个广义表是否相等即判断两个广义表中的元素是否完全相同。

如果两个广义表都为空,则相等;如果两个广义表的长度不相等,则不相等;否则,判断广义表的头是否相等,如果相等则判断广义表的尾是否相等。

复制广义表复制广义表即创建一个与原广义表相同的新广义表。

《数据结构(Python语言描述)》第5章 广义表

《数据结构(Python语言描述)》第5章 广义表
数据结构 (Python3
广义表是由n个类型相同的数据元素(a1、a2、……、an)组成的有限序列。广义表的元素可以是单个 元素,也可以是一个广义表。通常广义表记作:
GL=(a1,a2,…,an) 广义表有两种数据元素,分别是原子和子表,因此需要两种结构的节点,一种是表节点,用来表 示子表,如图5-1所示;一种是原子节点,用来表示原子,如图5-2所示。
OPTION
在广义表GL中,如果ai也是一个 广义表表,则称ai为广义表GL的 子表。
03 表头
OPTION
在广义表中GL中,a1如果不为空, 则称a1为广义表的表头。
04 表尾
OPTION
在广义表GL中,除了表头a1的其余 元素组成的表称为表尾。
05 深度
OPTION
广义表GL中括号嵌套的最大层数。
图5-3 广义表表节点
表节点由三个域组成:标志域tag,指向表头节点的指针域ph,指向表尾节 点的指针域pt。表节点的标志域tag=1。
5.3 存储结构
7
图5-4 广义表原子节点
原子节点由两个域组成:标志域tag,值域atom。原子节点的标志域tag=0。
节点的定义:
class Node:
def __init__(self, ph, pt, tag, atom):
表节点由三个域组成,即标志域tag、指向表头节点的指针域ph、指向表尾节点的指针域pt。表节点 的标志域tag=1。
原子节点由两个域组成,即标志域tag、值域atom。原子节点的标志域tag=0。
5.2 基本用语
4
01 原子
OPTION
在广义表GL中,如果ai为单个元 素,则称ai称为原子
02 子表

数据结构第06章广义表

数据结构第06章广义表

第6章广义表z6.1 广义表的基本概念z6.2 广义表的存储结构z6.3 广义表的操作算法16.1 广义表的基本概念广义表(列表)的概念-n( ≥0 )个表元素组成的有限序列,记作LS= ( a1, a1, a2, …, a n)LS是表名,a i是表元素,它可以是单个元素(称为原子) ,可以是表(称为子表) 。

n为表的长度。

n= 0 的广义表为空表。

n> 0时,表的第一个表元素称为广义表的表头(head),除此之外,其它表元素组成的表称为广义表的表尾(tail)。

2广义表举例:(1)A=()(2)B=(e)(3)C=(a, (b, c, d) )(4)D=(A,B,C)(5)E= (a , E)9任意一个非空广义表,均可分解为表头和表尾。

9对于一个非空广义表,其表头可能是原子,也可能是子表;而表尾一定是子表。

3广义表的基本操作:•结构的创建和销毁InitGList(&L); DestroyGList(&L); CreateGList(&L, S); CopyGList(&T, L);•状态函数GListLength(L); GListDepth(L);GListEmpty(L); GetHead(L); GetTail(L);•插入和删除操作InsertFirst_GL(&L, e);DeleteFirst_GL(&L, &e);•遍历Traverse_GL(L, Visit());66. 2 广义表的存储结构z由于广义表中的元素不是同一类型,因此难以用顺序结构表示,通常采用链接存储方法存储广义表,并称之为广义链表。

z由于广义表中有两种数据元素,原子或子表,因此,需要两种结构的结点:一种是表结点,一种是原子结点。

z下面介绍一种广义表的链式存储结构。

78扩展的线性链表表示法:-子表结点由三个域组成:标志域、表头指针域和指向下一个元素的指针域;-原子结点的三个域为:标志域、值域和指向下一个元素的指针域。

数据结构广义表

数据结构广义表
}GLNode2;
22
创建广义表
创建广义表就是按照所给的表示具体广义表的字符串 str创建一个广义表h。
和头链和尾链存储结构广义表的创建算法类同,原子 和子表存储结构的创建广义表操作同样可以分解为创建 表头广义表和创建表尾广义表。
把表示广义表的字符串str分解成表头字符串hstr和表 尾字符串str的函数DecomposeStr(str, hstr)设计和前面的 方法完全相同。
{ for(j = 0; j < i-1; j++) hstr[j] = str[j+1];
hstr[j] = '\0';
if(str[i] == ',') i++;
str[0] = '(';
for(j = 1; i <= n-2; i++, j++) str[j] = str[i];
str[j] = ')';
这样,还需要设计一个把表示广义表的字符串str分解 成表头字符串hstr和表尾字符串str的函数 DecomposeStr(str, hstr)。
14
void DecomposeStr(char str[], char hstr[])
{ int i, j, tag, n = strlen(str);
pre = h; for(max = 0; pre != NULL; pre = pre->val.subList.tail) { dep = GListDepth(pre->val.subList.head);
if(dep > max) max = dep; } return max + 1; }

c语言 广义表

c语言 广义表

C语言广义表1. 什么是广义表?广义表(Generalized List),简称GList,是一种线性链表的扩展结构,也是一种特殊的树结构。

与传统的线性链表不同,广义表的节点可以存储原子数据和子表(也就是另一个广义表)。

在C语言中,可以使用指针和结构体来实现广义表。

每个节点包含两个指针域,分别指向下一个节点和子表。

通过这种方式,可以灵活地表示复杂的数据结构。

2. 广义表的表示方法广义表有两种常用的表示方法:括号表示法和逻辑列表法。

2.1 括号表示法括号表示法使用括号来标识子表,并用逗号分隔元素。

例如,(1, (2, 3), (4, (5, 6)))表示一个包含三个元素的广义表,其中第一个元素是原子数据1,第二个元素是一个包含两个原子数据2和3的子表,第三个元素是一个包含两个原子数据4和另一个包含两个原子数据5和6的子表。

2.2 逻辑列表法逻辑列表法使用空格或其他特殊符号来分隔元素,并用一对方括号将所有元素括起来。

例如,[1, [2 3], [4 [5 6]]]表示同样的广义表。

3. 广义表的操作广义表支持一系列的操作,包括创建、插入、删除、查找等。

3.1 创建广义表可以通过递归的方式创建广义表。

首先创建一个节点,然后判断当前元素是原子数据还是子表。

如果是原子数据,则将其存储在节点中;如果是子表,则递归创建子表并将其存储在节点中。

3.2 插入元素插入元素可以分为两种情况:在指定位置前插入一个新元素和在指定位置后插入一个新元素。

在指定位置前插入一个新元素时,需要先找到要插入位置的前一个节点,然后创建一个新节点,并将新节点的指针域指向要插入位置的节点,再将要插入位置的前一个节点的指针域指向新节点。

在指定位置后插入一个新元素时,需要先找到要插入位置的节点,然后创建一个新节点,并将新节点的指针域指向要插入位置的下一个节点,再将要插入位置的节点的指针域指向新节点。

3.3 删除元素删除元素也可以分为两种情况:删除指定位置上的元素和删除指定值的元素。

数据结构课件PPT数组和广义表

数据结构课件PPT数组和广义表
T.mu=M.nu; T.nu=M.mu; T.tu=M.tu; if (T.tu)
{ q=1; for (col=1;col<=T.mu;++col) for(p=1;p<=M.tu;++p) if ( M.data[p].j==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; ++q; } }
(row) (col) (value)
[0] 1 4 22
[0] 1 5 91
[1] 1 7 15
[1] 2 2 11
[2] 2 2 11
[2] 3 6 28
[3] 2 [4] 3来自6 17 4 -6[3] 4 [4] 4
1 22 3 -6
[5] 4 6 39
[5] 6 2 17
[6] 5 1 91
[6] 6 4 39
cpot[1]=1 cpot[col]=cpot[col-1]+num[col-1]
稀疏矩阵的快速转置(算法5.2)
Status FastTransposeSMatrix(TSMatrix M,TSMatrix &T) { T.mu=M.nu; T.nu=M.mu; T.tu=M.tu;
if (T.tu) { for (col=1;col<=M.nu;++col) num[col]=0; for (t=1;t<=M.tu;++t) ++num[M.data[t].j]; cpot[1]=1; for ( col=2;col<=M.nu;++col) cpot[col]=cpot[col-1]+num[col-1]; for (p=1;p<=M.Tu;++p) { col=M.data[p].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]; } }

数据结构数组和广义表

数据结构数组和广义表

数据结构05数组与广义表数组与广义表可以看做是线性表地扩展,即数组与广义表地数据元素本身也是一种数据结构。

5.1 数组地基本概念5.2 数组地存储结构5.3 矩阵地压缩存储5.4 广义表地基本概念数组是由相同类型地一组数据元素组成地一个有限序列。

其数据元素通常也称为数组元素。

数组地每个数据元素都有一个序号,称为下标。

可以通过数组下标访问数据元素。

数据元素受n(n≥1)个线性关系地约束,每个数据元素在n个线性关系地序号 i1,i2,…,in称为该数据元素地下标,并称该数组为n维数组。

如下图是一个m行,n列地二维数组A矩阵任何一个元素都有两个下标,一个为行号,另一个为列号。

如aij表示第i行j列地数据元素。

数组也是一种线性数据结构,它可以看成是线性表地一种扩充。

一维数组可以看作是一个线性表,二维数组可以看作数据元素是一维数组(或线性表)地线性表,其一行或一列就是一个一维数组地数据元素。

如上例地二维数组既可表示成一个行向量地线性表: A1=(a11,a12,···,a1n)A2=(a21,a22, ···,a2n)A=(A1,A2, ···,Am) ············Am=(am1,am2, ···,amn)也可表示成一个列向量地线性表:B1=(a11,a21,···,am1)B2=(a12,a22, ···,am2)A=(B1,B2, ···,Bm) ············Bn=(a1n,a2n, ···,amn)数组地每个数据元素都与一组唯一地下标值对应。

数据结构第五章 数组和广义表

数据结构第五章 数组和广义表

5.3.1
特殊矩阵
1、对称矩阵 在一个n阶方阵A中,若元素满足下述性质: aij = aji 1≤i,j≤n 则称A为对称矩阵。 a11 1 5 1 3 7 a21 a 22 5 0 8 0 0 a31 a32 a33 1 8 9 2 6 ……………….. 3 0 2 5 1 an 1 a n 2 a n 3 …a n n 7 0 6 1 3
第5章
数组和广义表
5.1 数组的定义
5.2 数组的顺序表示和实现
5.3 矩阵的压缩存储
5.3.1 特殊矩阵
5.3.2 稀疏矩阵
5.4 广义表的定义
5.1 数组的定义
数组-----线性表的扩展 A =(a0,a1,a2,…,an-1)
a00 a10 ┇ Am×n= ai0 ┇ am-1,0 a01 … a0j … a11 … a1j … ┇ ai2 … aij … ┇ am-1,2 … am-1,j … a0,n-1 a1,n-1 ai,n-1 am-1,n-1 α0 α1 ┇ Am×n= α i ┇ α m-1
Assign( &A, e, index1, ..., indexn) 赋值操作 初始条件:A是n维数组,e为元素变量,随后是n个下标值。 操作结果:若下标不超界,则将e的值赋给所指定的A的元 素,并返回OK。 对于数组来说一旦维数确定了,每个元素的下标确定了, 那么整个数组就确定了,这样的一个数组结构除了能改变 某元素的值,其他的不能再改变。
5.2 数组的顺序表示和实现
数组类型特点: 1) 只有引用型操作,没有加工型操作; 2) 数组是多维的结构,而存储空间是一个一维的结构。 有两种顺序映象的方式。
有两种顺序映像方法: 1)以行序为主序(行优先,先行后列):先存储行号较小 的元素,行号相同者先存储列号较小的元素;

数据结构广义表

数据结构广义表

数据结构广义表一、引言数据结构是计算机科学的基础,广义表是一种重要的数据结构。

广义表是在线性表的基础上扩展而来,可以包含任意类型的元素,包括另一个广义表。

本文将详细介绍广义表的概念、表示方法、基本操作以及应用。

二、概念1. 广义表定义广义表是一种线性结构,可以包含原子和子表两种类型的元素。

其中,原子可以是任何数据类型,而子表则是一个嵌套的广义表。

2. 广义表表示广义表可以用括号表示法来表示。

例如:(a, b, (c, d), e)就是一个包含4个元素的广义表,其中第3个元素为一个嵌套的广义表。

3. 广义表分类根据广义表中元素所属类型不同,可以将其分为两类:原子和子表。

- 原子:指不再能被分解成更小单位的元素。

- 子表:指由若干个元素组成的序列,每个元素既可以是原子也可以是另一个子列表。

三、表示方法1. 递归表示法递归表示法是一种常用且简单易懂的方法。

它将一个非空广义列表示为左括号、若干元素和右括号的形式,其中每个元素可以是原子或另一个广义表。

例如:(a, b, (c, d), e)就是一个递归表示法。

2. 链式存储表示法链式存储表示法是一种更加灵活的方法。

它将广义表表示为一个链表,每个节点有两个指针域,分别指向下一个元素和下一个子表。

例如:(a, b, (c, d), e)可以用链式存储表示法表示为:四、基本操作1. 头尾操作头尾操作是指对广义表中第一个元素或最后一个元素进行操作。

- 头部操作:获取广义表中的第一个元素。

- 尾部操作:获取广义表中的最后一个元素。

2. 插入操作插入操作是指在广义表中插入新的元素或子表。

- 插入原子:在广义列表示中插入新的原子。

- 插入子表:在广义列表示中插入新的子列表。

3. 删除操作删除操作是指从广义列表示中删除某个元素或子列表。

- 删除原子:从广义列表示中删除某个原子。

- 删除子表:从广义列表示中删除某个子列表。

五、应用场景1. 树结构树结构可以用广义表来表示。

数据结构_广义表的运算

数据结构_广义表的运算

数据结构_广义表的运算数据结构——广义表的运算在计算机科学的数据结构领域中,广义表是一种较为复杂但又十分有趣和实用的数据结构。

它就像是一个“大容器”,可以容纳各种各样的数据元素,包括其他的广义表。

广义表的定义相对灵活,它可以是空表,也可以是由单个元素或者多个元素组成的表。

这些元素可以是原子,比如整数、字符等不可再分的数据;也可以是子表,也就是另一个广义表。

那么,广义表有哪些常见的运算呢?首先就是表头和表尾的获取。

表头指的是广义表中的第一个元素,如果这个元素本身是一个子表,那么这个子表整体就是表头。

而表尾则是除了表头之外的其余部分。

比如说,对于广义表`(a, (b, c), d)`,其表头是`a` ,表尾是`((b, c), d)`。

接下来是广义表的长度和深度的计算。

长度指的是广义表中元素的个数,需要注意的是,子表算一个元素。

比如`(a, (b, c), d)`的长度是3 。

而深度则是指广义表中括号嵌套的层数,空表的深度为1 。

对于`(a, (b, (c)))`,其深度为 3 。

广义表的创建也是一项重要的运算。

我们可以通过逐个输入元素的方式来创建广义表。

在创建过程中,需要明确每个元素是原子还是子表,以正确构建广义表的结构。

广义表的复制运算也必不可少。

这就像是给一个广义表做了一个“克隆”,得到一个完全相同的副本。

在复制过程中,需要注意对原子和子表的分别处理,确保复制的准确性。

插入和删除操作在广义表中同样有着重要的应用。

比如,我们可以在广义表的指定位置插入一个新的元素或者子表,也可以删除指定位置的元素或者子表。

合并广义表则是将两个或多个广义表组合成一个新的广义表。

在合并过程中,需要考虑元素的顺序和结构,以保证合并后的广义表符合预期。

遍历广义表是对广义表中所有元素进行访问的操作。

常见的遍历方式有深度优先遍历和广度优先遍历。

深度优先遍历就像是在探索一个迷宫,沿着一条路径一直走到底,然后再回溯;而广度优先遍历则是先访问同一层的元素,再依次访问下一层。

数据结构29:广义表的长度和深度

数据结构29:广义表的长度和深度

数据结构29:⼴义表的长度和深度⼴义表的长度通过前⼀节对⼴义表的介绍,例⼦中给出了⼏个⼴义表的长度。

例如:空表的长度为 0,只含有⼀个原⼦的⼴义表长度为 1,等等。

⼴义表的长度指的是⼴义表中数据元素的数量。

这⾥需要指明的是,⼀个⼴义表中,⼀个原⼦算做是⼀个元素,⼀个⼦表也只算做⼀个元素。

在 LS = (a1,a2,…,a n) 中,a i表⽰原⼦或者⼦表, LS 的长度为 n。

⼴义表的深度⼴义表的深度,指的是⼴义表中括号的重数。

例如:C=(a,(b,c,d)):图1 ⼴义表C的深度图1中,从前往后数左括号的数量就是⼴义表C的深度,为2;也可以从右往左数右括号的数量(红⾊)。

求解⼴义表的深度求⼴义表的深度之前,⾸先要将⼴义表⽤某个数据结构表⽰出来,在前边学习⼴义表时,介绍了两种表⽰⼴义表的⽅法。

这⾥采⽤的⽅法是第⼀种。

表⽰结构为:(拿⼴义表C为例)⼴义表第⼀节中有具体实现的代码,实现函数为:creatGlist(Glist C)。

这⾥不再过多介绍。

求⼴义表深度的算法⽤到的是递归的思想,解题思路是:1. 从⼴义表 C 的开头位置,⼀次遍历表中每个数据元素:当遍历对象为原⼦时,返回原⼦的深度为 0 ;遍历对象为表 C 的⼦表时,继续遍历⼦表中的数据元素。

2. 递归的出⼝有两个:当遍历对象为原⼦时,返回 0 ;遍历对象为空表时,返回 1 (空表的深度为 1 );3. 设置⼀个初始值为 0 的整形变量 max ,⽤ max 和遍历过程中返回的整形数值进⾏⽐较,取⼤的那⼀个,知道程序结束,max + 1就是⼴义表的深度。

实现代码为:int GlistDepth(Glist C){ //如果表C为空表时,直接返回长度1; if (!C) { return1; } //如果表C为原⼦时,直接返回0; if (C->tag == 0) { return0; } int max = 0; //设置表C的初始长度为0; for (Glist pp=C; pp; pp=pp->ptr.tp) { int dep = GlistDepth(pp->ptr.hp); if (dep>max) { max = dep; //每次找到表中遍历到深度最⼤的表,并⽤max记录 } } //程序运⾏⾄此处,表明⼴义表不是空表,由于原⼦返回的是0,⽽实际长度是1,所以,此处要+1; return max+1;}完整代码演⽰#include <stdio.h>#include <stdlib.h>typedef struct GLNode{ int tag; //标志域 union { char atom; //原⼦结点的值域 struct { struct GLNode *hp, *tp; }ptr; //⼦表结点的指针域,hp指向表头;tp指向表尾 };}*Glist, GNode;Glist creatGlist(Glist C){ //⼴义表C C=(Glist)malloc(sizeof(GNode)); C->tag = 1; //表头原⼦‘a’ C->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.hp->tag = 0; C->ptr.hp->atom = 'a'; //表尾⼦表(b,c,d),是⼀个整体 C->ptr.tp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->tag = 1; C->ptr.tp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.tp = NULL; //开始存放下⼀个数据元素(b,c,d),表头为‘b’,表尾为(c,d) C->ptr.tp->ptr.hp->tag = 1; C->ptr.tp->ptr.hp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.hp->tag = 0; C->ptr.tp->ptr.hp->ptr.hp->atom = 'b'; C->ptr.tp->ptr.hp->ptr.tp = (Glist)malloc(sizeof(GNode)); //存放⼦表(c,d),表头为c,表尾为d C->ptr.tp->ptr.hp->ptr.tp->tag = 1; C->ptr.tp->ptr.hp->ptr.tp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->tag = 0; C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->atom = 'c'; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp = (Glist)malloc(sizeof(GNode)); //存放表尾d C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->tag = 1; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->tag = 0; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->atom = 'd'; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.tp = NULL; return C;}//求⼴义表的深度,递归调⽤int GlistDepth(Glist C){ if (!C) { return1; } if (C->tag == 0) { return0; } int max = 0; for (Glist pp=C; pp; pp=pp->ptr.tp) { int dep = GlistDepth(pp->ptr.hp); if (dep>max) { max = dep; } } return max+1;}int main(int argc, const char *argv[]){ Glist C = creatGlist(C); printf("%d", GlistDepth(C)); return0;}运⾏结果:2。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

struct lnode *link;
} GLNode;
//指向下一个元素
//广义表结点类型定义
C a b
C 1

C a c d b c d
0
a
1

0
b
0
c
0
d

广义表的存储结构
广义表的两种基本情况 :
g2 1

g1
1


*
*
*
*

*
*

第 1 个元素 (a)空表
第 2 个元素 (b)非空表
第 n 个元素
5.2
广义表的存储结构
广义表是一种递归的数据结构 , 因此很难为每个 广义表分配固定大小的存储空间,所以其存储结构只 好采用动态链式结构。
第一种链式存储结构(存放表头和表尾)
表结点
原子结点
tag=1
hp
tp
tag=0
atom
typedef enum{ATOM, LIST} ElemTag; //ATOM==0: 原子; LIST==1:子表 typedef struct GLNode{ ElemTag tag; union{ AtomType atom; struct {Struct GLNode *hp, *tp;} ptr; } } *Glist;
第5章-2
1 2 3
广义表
广义表的定义 广义表的存储结构 广义表的运算
本章小结
5.1
广义表的定义
广义表简称表,它是线性表的推广。一个广义 表是 n(n≥0) 个元素的一个序列 ,若 n=0 时则称为空 表。设 ai为广义表的第 i个元素 ,则广义表 GL的一 般表示与线性表相同:
GL=(a1,a2,…,ai,…,an) 其中n表示广义表的长度,即广义表中所含元 素的个数,n≥0。如果ai是单个数据元素,则ai是广 义表GL的原子;如果ai是一个广义表,则ai是广义 表GL的子表。
空表
LS = NULL
Hale Waihona Puke 指向表尾的指针非空表 LS
tag=1 指向表头的指针
若表头为原子,则为 否则,依次类推。
tag=0 atom
A=( ) C=(a,(b,c,d))
A=NULL B 1 0 e ^ 即: A C 1 0 a
B= ( e ) D=( A , B , C ) ^
1 1 ^ 1 1 ^
f(g)=
1 MAX{f(subg)}+1
int GLDepth(GLNode g) //求带头结点的广义表g的深度 { int max=0,dep; if (g->tag==0) return 0; //为原子时返回0 g=g->val.sublist; //g指向第一个元素 if (g==NULL) return 1; //为空表时返回1 while (g!=NULL) //遍历表中的每一个元素 { if (g->tag==1) //元素为子表的情况 { dep=GLDepth(g); //递归调用求出子表的深度 if (dep>max) max=dep; //max为同一层所求过的子表中深度的最大值 } g=g->link; //使g指向下一个元素 } return(max+1); //返回表的深度 }
链接起来的,所以可把它看做是由link域链接起来的
单链表。这样,求广义表的长度就是求单链表的长度,
可以采用以前介绍过的求单链表长度的方法求其长
度。
求广义表长度的非递归算法如下:
int GLLength(GLNode g) //g为一个广义表头结点的指针 { int n=0; g=g->val.sublist; //g指向广义表的第一个元素
为原子的情况 :
g3 0 a

A=( ) C=(a,(b,c,d))
B= ( e ) D=( A , B , C )
A B
1 ^ ^
1
^
C
1
0 a
^
1 0 b ^ 0 c 0 d
0 e ^ D 1 1 ^ 1
1
^
5.3
1. 求广义表的长度
广义表的运算
在广义表中,同一层次的每个结点是通过link域
0 b
D 1 ^ 1 1 ^
0 c
0 d
ls =( a , ( ) , ( ( b , c ) , d ) ) ls
1 0 a 1 ^ 1 1 1 0 b 1 0 ^ c ^ 1 0 ^ d
第二种链式存储结构(存放孩子和兄弟)
typedef struct lnode { int tag; union { ElemType data; struct lnode *sublist; } val; //结点类型标识
为了简单起见 , 下面讨论的广义表不包括前面 定义的再入表和递归表 , 即只讨论一般的广义表。 另外 ,我们规定用小写字母表示原子 ,用大写字母表 示广义表的表名。例如: A=( )
B=(e)
C=(a,(b,c,d))
D=(A,B,C)=((),(e),(a,(b,c,d)))
E=((a,(a,b),((a,b),c)))
广义表的应用:
人工智能领域的表处理语言LISP; 多元多项式的表示; 用来表示树、图。
广义表具有如下重要的特性: (1)广义表中的数据元素有相对次序; (2)广义表的长度定义为最外层包含元素个数; (3)广义表的深度定义为所含括号的重数。其中,原子 的深度为0,空表的深度为1; (4)广义表可以共享;一个广义表可以为其他广义表 共享;这种共享广义表称为再入表; (5)广义表可以是一个递归的表。一个广义表可以是 自已的子表,这种广义表称为递归表。递归表的深度 是无穷值,长度是有限值; (6)任何一个非空广义表GL均可分解为表头 head(GL) = a1和表尾tail(GL) = ( a2,…,an) 两部分。
如果把每个表的名字 (若有的话 )写在其表的前面 ,则 上面的5个广义表可相应地表示如下:
A()
B(e)
C(a,(b,c,d))
D(A(),B(e),C(a,(b,c,d)))
E((a,(a,b),((a,b),c)))
若用圆圈和方框分别表示表和单元素,并用线段把表 和它的元素(元素结点应在其表结点的下方)连接起来,则 可得到一个广义表的图形表示。例如 , 上面五个广义表 的图形表示如下图所示。
A()
B(e)
C(a,(b,c,d))
D(A(),B(e),C(a,(b,c,d)))
E((a,(a,b),((a,b),c)))
A B e a b c d C A e D B a b c d C a a b a b c E
当广义表Ls非空时,称第一个元素为Ls的表头, 称其余元素组成的子表为Ls的表尾。 广义表的基本操作: 取表头:GetHead(Ls) 取表尾:GetTail(Ls)
本章小结 本章的基本学习要点如下: (1)掌握广义表的定义。 (2)重点掌握广义表的链式存储结构。 (3) 掌握广义表的基本运算 , 包括创建广义表、 输出广义表、求广义表的长度和深度。
(4)灵活运用广义表这种数据结构解决一些综合 应用问题。
while (g!=NULL)
{ n++; g=g->link;
}
return n; }
2. 求广义表的深度 对于带头结点的广义表 g,广义表深度的递归定义 是它等于所有子表中表的最大深度加1。若g为原子, 其深度为0。 求广义表深度的递归模型f( )如下:
0 若g为原子 若g为空表 其他情况,subg为g的子表
相关文档
最新文档