广义表的定义(精)

合集下载

3.4 广义表

3.4 广义表

((b,c,d)) C → 1 a 0 a 1
((b,c,d)) C → 1 a 0 a 1 (b,c,d)
((b,c,d)) C → 1 a 0 a 1 () (b,c,d)
((b,c,d)) C → 1 a 0 a 1 ^ () (b,c,d)
((b,c,d)) C → 1 a 0 a 1 1 ^ () (b,c,d)
3.4.2 广义表的存储结构
1. 头尾表示法
表结点 tag=1 hp tp
指向表尾的指针
原子结点 tag=0 data
指向表头的指针
class GLNode{ private: int tag; tag=0 data union { ptr tag=1 DataType data; hp tp struct { GLNode *hp,*tp; }ptr; }; };//GLNode
2. 孩子兄弟表示法 有孩子结点 tag=1 hp tp
指向第一个孩子的指针 指向兄弟的指针
无孩子结点 tag=0 data tp
class GLNode{ private: int tag; union { DataType data; GLNode *hp; }; GLNode * tp; };//GLNode
例1
参赛队清单的表示。 参赛队清单的表示。
参赛队清单=(俄罗斯,巴西,东道主,古巴,美国,韩国,日本 参赛队清单 俄罗斯,巴西,东道主,古巴,美国,韩国,日本) 俄罗斯 东道主= 国家队 香港队,澳门队) 国家队, 东道主 (国家队,香港队,澳门队 韩国= 韩国 ( ) (俄罗斯,巴西,(国家队,香港队,澳门队 ,古巴,美国,( ),日本 俄罗斯,巴西, 国家队 香港队,澳门队),古巴,美国, ,日本) 国家队, 俄罗斯

广义表

广义表

一、基本概念 广义表是线性表的推广。线性表中的元素仅限于原子项 单 广义表是线性表的推广。线性表中的元素仅限于原子项(单 原子项 个数据元素),即不可以再分,而广义表中的元素既可以是 个数据元素 ,即不可以再分,而广义表中的元素既可以是 原子项,也可以是子表(另一个线性表 另一个线性表)。 如果 如果a 原子项,也可以是子表 另一个线性表 。 (如果 i是单个数 据元素,则称 则称a 据元素 则称 i为广义表的原子 ) 1.广义表的定义 . 广义表是n≥0个元素a …, 的有限序列, 广义表是 n≥0个元素a0, a1, …,an-1的有限序列, 其中每一 个元素 个 ai 或 者 是 原 子 , 或 者 是 一 个 子 表 。 广 义 表 通 常 记 为 GL=(a0,a1,…,an-1), 其中 为广义表的名字, 为广义表的 , 其中GL为广义表的名字 , n为广义表的 为广义表的名字 长度, 每一个a 为广义表的元素。但在习惯中, 长度, 每一个 i为广义表的元素。但在习惯中,一般用大写 字母表示广义表 小写字母表示原子。 表示广义表, 字母表示原子 字母表示广义表,小写字母表示原子。 称第一个元素a 为广义表GL的表头,其余部分 其余部分(a 称第一个元素 0为广义表 的表头 其余部分 1,...an-1)为GL 为 表尾,分别记作 的表尾 分别记作 head(GL)= a0 和 tail(GL)= (a1,...an-1)
tag=1
hp
tp
tag=0
atom
语言描述结点的类型如下: 用C语言描述结点的类型如下: 语言描述结点的类型如下 Typedef enum{Atom, LIST } Elemtag; typedef struct node { Elemtag tag; union{ AtomType atom; struct{struct node *hp,*tp;} ptr; }; }*GList;

第三章广义表

第三章广义表

void Creat(GLNode *&GL) 输入:(#),a,((b,c),d); 输入: { char ch; 1: cin>>ch; Creat(GL) Creat(GL-> sublist) sublist 2:if(ch==‘#’) GL=NULL; 1:ch=‘(’ 1:ch=‘#’ 3:else if( ch==‘(‘) { if( 2,3, 4, 2:GL=^ 4:GL=new GLNode; GL->tag=true; GL5: ① 8:ch=‘)’ 5:Creat(GL5:Creat(GL->sublist);// ① } else { 8: ch=‘,’ 9: Creat(GL-> next next) 6: GL=new GLNode; GL->tag=false; GL9: 1:ch=‘a’ 7: GL->data=ch; } GL10: ② 8: cin>>ch; 2,3,6,7, 9:if(GL==NULL) 9:if(GL==NULL) ; 8:ch=‘,’ 10:else if(ch==‘,’) Creat(GL->next);//② if(ch==‘,’) Creat(GL->next);//② 10: ② 11: else if((ch==‘)’)||(ch==‘;’)) GL->next=NULL; GL0 a } 1 ^
1:max=0 2,3, ①
4:dep=1 5:max=1 6:GL=70 2,3,6:GL=^
7:return 2
3、建立广义表 如:(a,(#),b,c,(d,(e))); 建立广义表时,字符的情况: 建立广义表时,字符的情况: (1)当碰到左括号时 表明它是一个表元素的开始, (1)当碰到左括号时,表明它是一个表元素的开始,则应建立 一个由GL指向的表结点 并用它的sublist域作为子表的 指向的表结点, 一个由GL指向的表结点,并用它的sublist域作为子表的 表头指针进行递归调用,来建立子表的存储结构; 表头指针进行递归调用,来建立子表的存储结构; (2)当碰到一个英文字母时 表明它是一个单元素, (2)当碰到一个英文字母时,表明它是一个单元素,则应建立 一个由GL指向的单元素结点 指向的单元素结点; 一个由GL指向的单元素结点; (3)当碰到一个“#”字符 (3)当碰到一个“#”字符时,表明它是一个空表,则应置GL 字符时 表明它是一个空表,则应置GL 为空。 为空。 (4) 当建立了一个由GL指向的结点后, 当建立了一个由GL指向的结点后, 指向的结点后 接着碰到逗号字符时 表明存在后继结点, ①接着碰到逗号字符时,表明存在后继结点,需要建立当前 结点的后继表, 结点的后继表, 碰到右括号或分号字符时,表明当前所处理的表已结束, ②当碰到右括号或分号字符时,表明当前所处理的表已结束, 应置当前结点的next为空 为空。 应置当前结点的next为空。

数据结构 第5章广义表

数据结构 第5章广义表

if(i<n){ hstr=str.substr(1,i-2); str="("+str.substr(i,n-i); } else{ hstr=str.substr(1,n-2); str=""; } return hstr; }
何谓"递归函数 ? 何谓 递归函数"? 递归函数
一个含直接或间接调用本函数语句的函数被 称之为递归函数,它必须满足以下两个条件: 称之为递归函数,它必须满足以下两个条件: 在每一次调用自己时,必须是(在某种意义 ①在每一次调用自己时,必须是 在某种意义 更接近于解; 上)更接近于解; 更接近于解 函数中必须有一个终止处理或计算的准则。 ②函数中必须有一个终止处理或计算的准则。
的存储结构。 例:广义表 L=(a,(x,y),((z))) 的存储结构。
可由对L进行表头和表尾的分析得到 若列表不空 可由对 进行表头和表尾的分析得到--若列表不空, 进行表头和表尾的分析得到 若列表不空, 则可分解成表头和表尾(采用头尾链表存储结构)。 则可分解成表头和表尾(采用头尾链表存储结构)。 分析: 分析: ①L为一非空列表 为一非空列表
// 将非空串 分割成两部分: 将非空串str分割成两部分 分割成两部分: // hsub为最外层第一个 之前的子串,str为之后的子串 为最外层第一个','之前的子串 为最外层第一个 之前的子串, 为之后的子串 string sever(string& str) { int n,k,i; // k记录尚未配对的左括号个数 记录尚未配对的左括号个数 string ch,hstr; n=str.length(); for(i=0,k=-1; i<n&&(ch!=","||k!=0); ++i) { // 搜索最外层的第一个逗号 ch=str.substr(i,1); //从第 个位置起,取1个字符 从第i个位置起 从第 个位置起, 个字符 if(ch=="(") ++k; else if(ch==")") --k; }

数据结构广义表

数据结构广义表

结点结构是无论什么结点都有三个域:
第一个域是结点类型标志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

数据结构(广义表)

数据结构(广义表)

3 广义表的存储结构
形式描述为: 形式描述为:
typedef enum{ ATOM, LIST }ElemTag typedef struct GLNode { //定义广义表结点 ElemTage tag; //公共部分,用以区分 原子结点和表结点 //原子结点和表结点的联合部分 Union{ atom;//原子类型结点域, AtomType atom; // AtomType AtomType由用户定义 Struct { struct GLNode *hp, *tp; }ptr; }; //表结点的指针域, //ptr.hp 与ptr.tp ptr.tp分别指向广义表的表头和表尾。 ptr.hp ptr.tp }*Glist; }*Glist; //广义表类型
应用: 元多项式的表示 应用:M元多项式的表示
对任何一个M元多项式P,先确定一个主变元,于是它可看成 对任何一个M元多项式P 先确定一个主变元, 主变元的一元多项式,但它的系数可能是一个多项式, 主变元的一元多项式,但它的系数可能是一个多项式,也可能是 一个常数。于是P 一个常数。于是P可表为一个线性表 ),…,( P=((α1 , expn1),(α2 ,expn2), ,( αn ,expnn)) 其中每个α 可能是一个常数,也可能又是一个多项式; 其中每个αi可能是一个常数,也可能又是一个多项式;对于每一 个多项式α 又可以确定一个主变元( 个多项式αj ,又可以确定一个主变元(可称为原多项式的第二变 ),从而 可表为下一级的一元多项式, 从而, 元),从而,可表为下一级的一元多项式,其系数又可能性是常 也可能是多项式; ;直到最后纯粹的一元多项式。 数,也可能是多项式;…;直到最后纯粹的一元多项式。 所以M元多项式,最好用广义表来表示。其元素结点如下图: 所以M元多项式,最好用广义表来表示。其元素结点如下图:

第4章数组与串第4节广义表

第4章数组与串第4节广义表

// 为原子时输出元素值
if (p->tag==1) cout << ")";
// 为表结点时输出')&)
{ cout << ",";
GLDisp (p->link);
// 递归输出后续表的内容
}
}
}
第4章 数组与串 第4节 广义表
3. 求广义表的长度 所谓广义表的长度是指在广义表中元素个
//p指向广义表的第一个元素
while (p!=NULL)
{ n++;
p=p->link;
}
return n;
}
第4章 数组与串 第4节 广义表
4.广义表的复制 复制一个广义表的算法思想:对于一个广义
表的头结点*p,若为空,则返回空指针;若为子 表,则递归复制子表;否则复制原子结点,然后 递归复制后续表。算法结束返回广义表链表指针。
用字符串变量 s 来表示一个广义表的括号表 达式,从头到尾扫描 s 的每一个符号:
(1)当遇到是左括号,说明是一个表的开始, 则建立一个由 h 指向的表的结点,并用它的dlink 域作为子表的表头指针,进行递归调用;
第4章 数组与串 第4节 广义表
(2)当扫描到一个字母,说明它是一个原子, 则建立一个由h指向的原子结点;
数,由于广义表在同一层次的每个结点是通过 link域链接起来的,所以可把它看做是由link域链 接起来的单链表。这样,求广义表的长度就变成 求单链表的长度了。
第4章 数组与串 第4节 广义表
int GLLength(GLNode *p)
//p为广义表附加头结点的指针
{
int n=0;

广义表

广义表

Union 结点的联合部分*/
/*表结点和原子
{ ElemType data; 点的数据域*/
/*data是原子结
struct
{ struct GLNode *hp,*tp; /*hp和tp分别指向表头和表尾*/
} ptr
}
} GList;
/*广义表类型*/
上一页 下一页 返回
6.2 广义表的存储结构
下一页 返回
6.2 广义表的存储结构
6.2.1 头尾表示法 若广义表不空,则可分解称表头和表尾;反之,一对确定的表头和表尾
可唯一地确定一个广义表。头尾表示法就是根据这一性质设计而成的一 种存储方式。图6-2 头尾表示法的结点形式 广义表的表尾一定还是广义表,但表头可能是表也可能是单元素(原 子)。在头尾表示法中,如果只使用一种表头结点,同样会遇到存储空 间浪费的问题。因此,表中应该有两类结点:表结点和单元素(原子) 结点,如图6-2所示。表结点包括3个域:标志个域:标志域和数据域。如果 标志域tag=1,则表示该结点为表结点。 如果标志域tag=0,则表示该结点为原子结点。
上一页
返回
6.2 广义表的存储结构
广义表的存储一般采用链式存储结构,这是因为广义表中的数据元素可 以是原子也可以是广义表,各元素类型不同,占用的存储空间大小相差 很大,如果采用顺序存储结构表示会造成很大的空间浪费,操作也不方 便。在链式存储方式下,每个表元素,不论是原子或是表,都可用一个 结点表示,不同的结点其存储空间大小不同。按结点形式的不同,广义 表的链式存储结构又可以分为两种存储方式。一种称为头尾表示法,另 一种称为孩子兄弟表示法。
上一页 下一页 返回
6.1 广义表的定义及基本操作
称表的第一个元素a1,为广义表GL的表头,其余部分(a2,…,ai,…,an)为 GL的表尾,分别记作head(GL)=a1和tail=(a2,…,ai,…,an)。显然,表头 可能是单元素也可能是广义表,表尾却一定是广义表,空表无表头表尾。 仍取上面示例:

广义表

广义表
(4) 广义表可被其它广义表所共享。例如上述例子中广义表B同时也 是广义表 D 中的一个子表;
(5) 广义表可以是一个自递归的表。例如上述例子中的广义表 F
,自递归的广义表的长度是个有限值,而深度为无限值。
5.广义表的分类
(1)线性表:元素全部是原子的广义表。 (2)纯表:与树对应的广义表,见图5-8的(c) 、(d)、 (e) 。 (3)再入表:与图对应的广义表(允许结点共享), (4)递归表:允许有递归关系的广义表,例如E=(a,E)。 这四种表的关系满足:递归表再入表 纯表 线性表
图 5-8 广义表的图形表示
从图5-8可以看出:广义表的图形表示像倒着画的一棵树, 树根结点代表整个广义表,各层树枝结点代表相应的子表,树叶
结点代表单元素或空表(如A表)。
4.广义表的深度
一个广义表的深度是指该广义表展开后所含括号的层数。 例如,A=(b,c)的深度为 1,B=(A,d) 的深度为2,C=(f,B,h) 的深度为
已知以下矩阵,对应三元组是: 0 3 0 0 0 2 0 0 0 5
0 -1
0
0
0
0
2.6 广义表的定义
2.6.1 广义表的定义
1.广义表的定义
广义表也是线性表的推广,是一种多层次的线性结构,线性表
中的元素仅限于原子项,即不可以再分; 而广义表中的元素既可以是原子项,也可以是子表(另一个线 性表)。主要用于人工智能领域的表处理语言LISP语言。 广义表是n≥0个元素a1,a2,…,an的有限序列,其中每一个ai 或者是原子,或者是一个子表。广义表通常记为 LS=(a1,a2,…,an),其中 LS 为广义表的名字, n 为广义表的长度, 每一个ai为广义表的元素。但在习惯中,一般用大写字母表示广 义表,小写字母表示原子。

广义表——精选推荐

广义表——精选推荐

⼴义表1.定义:⼴义表是⼀种复杂的数据结构,是线性表的扩展,能够表⽰树结构和图结构。

2.细分定义:⼴义表是n个数据元素a0,a1,...,an-1组成的有限序列,记为GList=(a0,a1,...,an-1)其中,(1)ai或为不可分的数据元素(称为原⼦),或为可再分的⼴义表(称为⼦表)。

(2)⼴义表的元素个数n称为⼴义表长度(特殊:当n=0时,为空表。

)(3)⼴义表的深度是指表格中所含括号的层数(特殊:原⼦的深度为0,空表的深度为1.)注意:如果⼴义表作为⾃⾝的⼀个元素,则称该⼴义表为递归表。

递归的深度是⽆穷指,其长度是有限值。

(4)为了区分原⼦和表,约定⼤写字母表⽰表,⼩写字母表⽰原⼦。

(5)另⼀种⼴义表表⽰称为⼜名表,约定每个表都要有名称,将名称写在表组成的括号前。

(6)⼴义表的语法:其中“()”作为⼴义表开始和结束的标记,“,”作为原⼦或⼦表的分隔符。

3.⼴义表的特性。

(1)线性结构。

(⼴义表是⼀种线性结构,数据元素之间是线性关系,只不过元素不⼀定都是原⼦了,如果元素都是原⼦,那么这个⼴义表就是线性表,所以说线性表是⼴义表的特例)(2)多层次结构,有深度。

(注意:⼴义表是树的扩展。

当限制表中成分不能共享和递归时,该⼴义树就是树,树中的叶⼦结点对应⼴义表中的原⼦,⾮叶结点对应⼦表)(3)可共享(⼀个⼴义表可作为其他⼴义表的⼦表,多个⼴义表可共享⼀些⼴义表。

(4)可递归(⼴义表是⼀个递归表,当⼴义表中有共享或递归成分的⼦表时构成图结构,与有根,有序,有向图对应。

4.⼴义表的图形表⽰a.说明:(1)当⼴义表L(a,b)的数据元素全部都是原⼦时,L为线性结构的线性表。

(2)当⼴义表L(c,L)的数据元素中有⼦表,但没有共享和递归成分时,T为树结构的纯表。

(3)当⼴义表L(d,L,T)的数据元素中有⼦表,并且有共享成分时,G为结构的再⼊表。

(4)当⼴义表L(e,Z)的数据元素中有⼦表且有递归成分时,Z为图结构的递归表。

零基础学数据结构 第8章 广义表

零基础学数据结构 第8章 广义表

(5)CopyGList(&T,L):复制广义表。由广义表L复制得到广义表T。复
制成功返回1;否则,返回0。
8.2 广义表的头尾链表表示与实现
8.2.1 广义表的头尾链表存储结构
因广义表中有两种元素:原子和子表,所以广义表的链表结点也分 为两种:原子结点和子表结点,其中,子表结点包含3个域:标志域、 指向表头的指针域和指向表尾的指针域。原子结点包含两个域:标志 域和值域。表结点和原子结点的存储结构如图8.1所示。
8.2 广义表的头尾链表表示与实现
(3)求广义表的长度。求广义表的长度只需要沿着表尾指针tp查找下去,统计子 表个数,直到tp为NULL为止。如果广义表是空表,则广义表的长度为0。否则, 将指针p指向结点的表尾指针,统计广义表的长度。 int GListLength(GList L) { int length=0; while(L) /*如果广义表非空,则将p指向表尾指针,统计表的长度*/ { L=L->ptr.tp;E就是一个递 Nhomakorabea的广义表。
任何一个非空广义表的表头可以是一个原子,也可以是一个广义表,而 表尾一定是一个广义表。例如: head(A)=(),tail(A)=(),head(C)=a,tail(C)=((b,c)), head(D)=A,tail(D)=(B,C) 其中,head(A)表示取广义表A的表头元素,tail(A)表示取广义表A的表 尾元素。
8.2 广义表的头尾链表表示与实现
求广义表的深度的算法实现如下。 int GListDepth(GList L) { int max,depth; GLNode *p; if(!L) /*如果广义表为空,则返回1*/ return 1; if(L->tag==ATOM) /*如果广义表是原子,则返回0*/ return 0; for(max=0,p=L;p;p=p->ptr.tp) /*逐层处理广义表*/ { depth=GListDepth(p->ptr.hp); if(max<depth) max=depth; } return max+1; }

黄佳棋广义表

黄佳棋广义表

5)对非空广义表,称第一个元素为广义表的表头,
其余元素组成的表称为广义表的表尾。
广义表举例

A=( ) ——A是一个空表,它的长度为零 B=(e,f) ——B有两个原子e,f,B的长度为2 C=(a,(b,c)) ——C有一个原子a和一个子表(b,c),C的长度为2 D=(B,A,C) ——D有三个子表B、A、C,D的长度为3
5. 3 广义表
5. 3 . 1 广义表的概念 5. 3 . 2 广义表的存储结构
黄佳棋整理
课件
一、广义表的Байду номын сангаас念
1 什么是广义表
广义表也称为列表,是线性表的一种扩展,也是数据元素的有限序列。 记作:LS = ( 1, 2, , n ) 其中,i 或为原子 或为广义表.
说 明:
1)广义表的定义是一个递归定义。通常用大写字母表示广义表的名称, 用小写字母表示原子。 2)在线性表中数据元素是单个元素,而在广义表中, 元素可以是 单个元素,称为原子;也可以是广义表,称为广义表的子表。 3)n 是广义表长度,即最外层括弧包含元素个数 。 4) 广义表的深度定义为所含括弧的重数; 注意:“原子”的深度为0 ; “空表”的深度为1 。
子和表均采用三个域的结点结构(“同构”)。结点中都有一个指针域tp指向后
继结点。原子结点中还包括标志域tag=0和原子值域atom;子表结点还包括标志 域tag=1和指向子表的指针hp。在画存储结构时,从左往右一个元素一个元素的 画,直至最后一个元素。
画出下列广义表的两种存储结构图
((),A,(B,(C,D)),(E,F))
L L= =( (a a, ( x, y ), ) ((x)) )) L
1 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. 树结构树结构可以用广义表来表示。

广 义 表

广 义 表
其实现方法是在该数据域中放一个指向那个子表的指针。 如图5-12所示。
1.广义表的结点类和表类的定义
广义表采用3个域的结点结构表示。
第一个域是tag域,tag =0,表示此结点是专用表头结点; tag=1,表示是单元素结点;tag=2,表示是子表结点。
第二个域ref/data / hlink由其tag域确定,当tag=0时,ref中 存放引用计数;当tag=1时,即为data域,此处假设存放 字符型数据;当tag=2时,即为hlink域,用来存放指向子 表表头的指针。
通常,广义表是用链表结构存储的。例如对LS1=('a', 'b', 'c', 'd'),可用图5-11所示的链表表示。 表结点中有两个域:数据域和指针域。指针LS1称为指向 表的外部指针,因为它不是定义在表结点内部的,定义 在表结点内部的指针叫做内部指针。
然而,当广义表中的元素是子表时,其链表表示就不象 上面LS1的那么简单了。例如,对LS2= (‘a’, (‘b’, ‘c’, (‘d’, ‘e’ , ‘f’) , ‘g’) , ‘h’ , (‘i’ , ‘j’)),表中有些表元素又是表。于 是就可考虑在链表的数据域中存放一个子表。
3. 最高一层的表结点个数(除表头结点外)即为表 的长度。
2.部分成员函数的实现
现给出部分成员函数的实现。 genlist:: genlist()_{ //构造函数 glnode *first =new glnode; //建立表头结点 first->tag = 0; first->ref = 0; first->tlink = NULL; }
LS = (α1 ,α2 , … , αn ) 其中LS是表名,表的长度为n。长度为0的广义表为空表。 一般用大写字母表示表名,用小写字母表示数据元素。如果 n≥1,则称α1 为广义表LS的表头(head),称(α2 , … , αn )为广 义表LS的表尾(tail)。

广义表

广义表

D=(A, B, C); E=((a, (a, b), ((a, b), c)))
A B e a b c d C A D B e a b c d C a a b a b c E
广义表 2. 广义表的基本操作 取表头 GetHead(LS) = a1。 取表尾 GetTail(LS) = (a2,a3,…,an)。 ①B=(e) GetHead(B) = e; GetTail(B) = ( ). ②A=(a, ((b, c), d, e)) GetHead( GetHead( GetTail(A))) = GetHead( GetHead( ( ((b, c), d, e) ) )) = GetHead( ((b, c), d, e) ) = ③A=( ); B = ( ( ) ) A空表,长度0,深度1,无表头和表尾; B长度1,深度2,表头( ),表尾( )。 练习:从广义表A=(a,b,(c,d),(e,(f,g)))中取出原子f,应该采取什 么样的操作?
广义表
C=(a, (b, c, d)) A=( ) A = NULL; (a, (b, c, d))
C 1
((b, c, d))
1

(b, c, d) (c, d)
0 a 1 1 1
(d)

0
b
0
c
0
d
广义表
D=( ); A= (a, b, c);
(a, b, c)
B=(A, A, D);
广义表
D=( )空表,长度为0,深度为1。 A=(a, (b, c)) 长度为2,第一个元素为原子a,第二 个元素为子表(b, c),深度为2。 B=(A, A, D) 长度为3, 其前两个元素为表A, 第 三个元素为空表D,深度为3。 C=(a, C) 长度为2递归定义的广义表,C相当于 无穷表C=(a,(a, (a,…))),深度无限。 递归表的深度是无穷值,长度是有限值。 F=((a, (a, b), ((a, b), c))) 长度为1,深度为4。

广义表的概念及抽象数据类型

广义表的概念及抽象数据类型
10
E1
1
1

0a
0 e∧ 1∧ 0 d∧ 0b
0 c∧
11
Байду номын сангаас
6
(5)判非空否GListNotEmpty(L) (6)取表头GetHead(L) (7)取表尾GetTail(L) (8)插入GListInsert(L, e) (9)删除GListDelete(L, e) (10)查找原子元素GListSearch(L, e) (11)撤消DestroyGList(L)
7
7.2 广义表的存储结构
头链和尾链存储结构
一个广义表可以由表头和表尾两部分组成,所以可以用一个头指针和一 个尾指针表示一个广义表。这样,头链和尾链结构中一个结点的结构由 一个标志域tag决定:当tag值为1时,该结点除标志域外还有一个头指 针域和一个尾指针域;当tag值为0时,该结点除标志域外还有一个原子 元素域。
1
一个广义表通常用一对圆括号括起来,这样当这个广义表中的某个数据元 素又是一个广义表时,就可以再用一对括号括起来。广义表中的原子数据元素 通常用小写字母表示,而广义表通常用大写字母表示。从结构上看一个广义表 对应了一棵树。例如,设有如下广义表: A = () B = (a, b, c) C = (d) D = (B, C) = ((a, b, c), (d)) E = (D, e) = (((a, b, c), (d)), e)。
2
广义表E的图形表示
E e
D
B
C
a
b
c
d
3
广义表的长度指广义表中数据元素(原子元素或广义表)的个数。如广义表 A的长度为0,广义表B的长度为3,广义表C的长度为1,广义表D的长度为2 (注意D中只有两个数据元素B和C),广义表E的长度为2。

广义表的定义

广义表的定义

广义表的定义
设广义表LS=(a1,a2,…,a n),当广义表非空时,a1称为广义表LS的表头:其余元素组成的表(a2,a3,…,a n)是LS的表尾;广义表中的元素个数为表的长度。

广义表的深度是指表中所包含的括号的重数(层数),最里层的括号是最低层,最外层的括号是最高层。

广义表的定义可以是传递的递归的定义。

(1)A=()空表,长度为零。

(2)B=(e)含一个原子,长度为1,表头为原子e,表尾为空。

(3)C=(a,(b,c,d))含一个原子a和子表(b,c,d),C 的长度为2.
(4)D=(A,B,C)长度为3,3个元素都为列表。

(5)E=(a,E)长度为2,是一个递归的表,相当于一个无限的列表E=(a,(a,(a,…)))。

例5.11广义表E=(a,(a,b),d,e,((i,j),k))的表头为(),表尾为(),长度为(),深度为()。

答:表头为a,表尾为((a,b),d,e,((i,j),k)),长度为5,深度为3.。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
0 若g为原子 若g为空表 其他情况,subg为g的子表
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); /*递归调用求出子表的深度 */ /*max为同一层所求过的子表中深度的最大值*/ if (dep>max) max=dep; } g=g->link; /*使g指向下一个元素*/ } return(max+1); /*返回表的深度*/ }
C a b c d
C a b c d
广义表的存储结构
广义表的情况 :
g2 1

g1
1


*
*
*
*

*
*

第 1 个元素 (a)空表
第 2 个元素 (b)非空表
第 n 个元素
为原子的情况 :
g3 0 a

typedef struct lnode { int tag; union { ElemType data; /*结点类型标识*/
A()
A B e a b c d C A e
B(e)
D B a b c d C
C(a,(b,c,d))
E
a a b a b c
D(A(),B(e),C(a,(b,c,d)))
E((a,(a,b),((a,b),c)))
8.2
广义表的存储结构
广义表是一种递归的数据结构 , 因此很难为每个 广义表分配固定大小的存储空间 ,所以其存储结构只 好采用动态链式结构。 有两类结点 ,一类为圆圈结点 ,在这里对应子表; 另一类为方形结点,在这里对应原子。
/*遇到')'字符,子表为空*/ /*新结点作为原子结点*/
/*串结束,子表为空*/ /*取下一个扫描字符*/ /*串指针后移一位*/ /*串未结束判断*/ /*当前字符为','*/ /*递归构造后续子表*/ /*串结束*/ /*处理表的最后一个元素*/ /*返回广义表指针*/
4. 输出广义表 以h作为带头结点的广义表的表头指针,打印输出 该广义表时,需要对子表进行递归调用。输出一个广 义表的算法如下:
如果把每个表的名字(若有的话)写在其表的前面, 则上面的5个广义表可相应地表示如下: A() B(e)
C(a,(Байду номын сангаас,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,C)=((),(e),(a,(b,c,d))) E=((a,(a,b),((a,b),c))) F=(a,F)=(a,(a,(a,…)))
广义表具有如下重要的特性:
(1)广义表中的数据元素是有顺序的;
(2)广义表的长度定义为最外层包含元素个数;
3. 建立广义表的链式存储结构
假定广义表中的元素类型ElemType为char类型,每
个原子的值被限定为英文字母。
并假定广义表是一个表达式, 其格式为:元素之间用
一个逗号分隔, 表元素的起止符号分别为左、右圆括号, 空表在其圆括号内不包含任何字符。例如“(a,(b,c,d))” 就是一个符合上述规定的广义表格式。
if (ch=='(')
{ h->tag=1;
/*当前字符为左括号时*/
/*新结点作为表头结点*/
h->val.sublist=CreatGL(s); /*递归构造子表并链到表头结点*/ }
else if (ch==')') h=NULL; else { h->tag=0; h->val.data=ch; } } else h=NULL; ch=*s; s++; if (h!=NULL) if (ch==',') h->link=CreatGL(s); else h->link=NULL; return h; }
生成广义表链式存储结构的算法如下:
GLNode *CreatGL(char *&s)
{ GLNode *h;char ch; ch=*s; s++; if (ch!='\0') { /*取一个扫描字符*/
/*串指针后移一位*/ /*串未结束判断*/
h=(GLNode *)malloc(sizeof(GLNode));/*创建新结点*/
求广义表长度的非递归算法如下:
int GLLength(GLNode *g) /*g为一个广义表头结点的指针*/ { int n=0; g=g->val.sublist; /*g指向广义表的第一个元素*/
while (g!=NULL)
{ n++; g=g->link;
}
return n; }
2. 求广义表的深度 对于带头结点的广义表 g,广义表深度的递归定义 是它等于所有子表中表的最大深度加1。若g为原子, 其深度为0。 求广义表深度的递归模型f()如下:
(3)广义表的深度定义为所含括弧的重数。其中,原 子的深度为0,空表的深度为1;
(4) 广义表可以共享;一个广义表可以为其他广义 表共享;这种共享广义表称为再入表; (5) 广义表可以是一个递归的表。一个广义表可以 是自已的子表。这种广义表称为递归表。 递归表的深度是无穷值,长度是有限值;
广义表具有如下重要的特性: (6) 任 何 一 个 非 空 广 义 表 GL 均 可 分 解 为 表 头 head(GL)和表尾tail(GL) 两部分。 表头是广义表的第一个元素: head(GL)= a1 表尾是广义表中除了表头之外的所有元素构成的 广义表 :tail(GL) = ( a2,…,an)
8.1
广义表的定义
广义表示一种递归定义的线性结构,广义表的 元素既可以是普通的数据元素,也可以是广义表。 对于GL=(a1,a2,…,ai,…,an)来说,如果ai是单个 数据元素,则ai是广义表GL的原子;如果ai是一个 广义表,则ai是广义表GL的子表。
我们规定用小写字母表示原子,用大写字母表示 广义表的表名。例如:
广义表的存储结构
广义表的两种存储结构: 1)子表分析法 2)表头、表尾分析法
本章小结
本章的基本学习要点如下:
(1)掌握广义表的定义。
(2)重点掌握广义表的链式存储结构。
(3)掌握广义表的基本运算 ,包括创建广义表、输出 广义表、求广义表的长度和深度。 (4)灵活运用广义表这种数据结构解决一些综合应 用问题。
练习
教材中p99习题1、2、3。
struct lnode *sublist;
} val; 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

广义表的存储结构
8.3
1. 求广义表的长度
广义表的运算
在广义表中 , 同一层次的每个结点是通过 link 域链 接起来的 , 所以可把它看做是由 link 域链接起来的单 链表。这样,求广义表的长度就是求单链表的长度,可 以采用以前介绍过的求单链表长度的方法求其长度。
第8章
8.1 8.2 8.3
广义表
广义表的定义 广义表的存储结构 广义表的运算
本章小结
8.1
广义表的定义
广义表简称表, 它是线性表的推广。一个广义 表是n(n≥0)个元素的一个序列: GL=(a1,a2,…,ai,…,an)
广义表的一般表示与线性表相同。
ai 为广义表的第 i 个元素, n 表示广义表的长 度 ,即广义表中所含元素的个数 ,n≥0。若 n=0时则 称为空表。
void DispGL(GLNode *g) /*g为一个广义表的头结点指针*/ { if (g!=NULL) /*表不为空判断*/ { if (g->tag==1) /*为表结点时*/ { printf("("); /*输出'('*/ if (g->val.sublist==NULL) printf(""); /*输出空子表*/ else DispGL(g->val.sublist); /*递归输出子表*/ printf(")"); /*为表结点时输出')'*/ } else printf("%c", g->val.data); /*为原子时输出元素值*/ if (g->link!=NULL) { printf(","); DispGL(g->link); /*递归输出后续表的内容*/ } } }
相关文档
最新文档