广义表基础
广义表的定义
线性表 线性表指的是n≥0个元素a1, a2, a3…的有序数列,并且线性表的元素具有原子性,即结构上是不可分割的一个整体。
广义表(Generalized list) 而广义表则是线性表的一种扩展延伸。相对于线性表,广义表最大的特点在于其元素既可以是一个确定的类型,同时也可以是另一个有不定数量的元素组成的表(广义表)。
不难看出从广义表的定义是递归的。广义表是线性表的递归数据结构。
广义表的基本概念
广义表的表示
我们通常可以用 GL = (a1, a2, a3… an)来表示一个广义表,其中n为表的长度,n>=0,当n==0时,我们称广义表为空表,GL为广义表的名字。
为了能更好的区分广义表中的元素我们有以下定义:
原子 如果ai是单个元素,我们称之为GL的原子
子表 如果ai是一个广义表,我们陈之为GL的子表
我们通常把广义表中的原子用小写字母表示,而子表用大写字母表示。例如
A=() //空表 B=(e) //只含有一个原子的广义表 C=(a,(b,c,d)) //含有一个原子和一个子表的广义表 D=(A,B,C)=((),(e),(a,(b,c,d))) //含有三个子表的广义表,且第一个表为空表 E=(a,E) //广义表 E 中有两个元素,原子 a 和它本身。这是一个递归广义表,等同于:E = (a,(a,(a,…)))。
广义表的深度和长度
广义表的长度: 广义表中元素的个数(包括原子和子表)
广义表的深度: 广义表中括号的最大层数叫广义表的深度。
广义表的表头和表尾
表头: 当广义表不为空表时,第一个元素(可能为子表和原子)称为表头
表尾: 除去表头,剩余元素组成的新广义表称为表尾
例如:
LS=(1,(1,2,3),5), 其中表头Head(LS)为原子1,表尾为Tail(LS)=((1,2,3),5) LS=(1), 其中表头Head(LS)为原子1,表尾为空表
广义表的存储结构
广义表是一种递归的数据结构,它的元素具有两种,因此很难为广义表分配固定的存储空间,所以其存储结构适合用链式存储结构。
为了能使原子和子表在结构上抱持一致,又容易区分我们通常采用如下结构:
广义表的第一种存储结构
用C语言表示为
typedef enum {ATOM,LIST } ElemTag; //ATOM==0:表示原子,LIST==1:表示子表 typedef struct GLNode { ElemTag tag; //公共部分,用以区分原子部分和表结点 union { //原子部分和表结点的联合部分 AtomType atom; //atom是原子结点的值域,AtomType由用户定义 struct { struct GLNode *hp, *tp;} ptr; // ptr是表结点的指针域,ptr.hp 和ptr.tp分别指向表头和表尾 }; } *Glist; //广义表类型
例子
表示(a,(b,c,d))
广义表的第二种存储结构
第二种表示形式实际上就只是在原子中添加了tp指针指向下一个原子和子表
用C语言实现:
Typedef enum { ATOM,LIST} ElemTag; //ATOM==0:表示原子,LIST==1:表示子表 Typedef struct GLNode { ElemTag tag; //公共部分,用以区分原子部分和表结点 union { //原子部分和表结点的联合部分 AtomType atom; //原子结点的值域 struct GLNode *hp; //表结点的表头指针 }; struct GLNode *tp; //相当于线性链表的next,指向下一个元素结点 } *Glist; //广义表类型Glist 是一种扩展的线性链表
列子
表示(a,(b,c,d))
广义表的计算(以第二种存储结构为例)
广义表长度的计算(类似于链表的长度,直接统计tp)
int GLLength(GLNode *g) //g为一个广义表头节点的指针 { int n=0; g=g->hp; //g指向广义表的第一个元素 while (g!=NULL) { n++; g=g->tp; } return n; }
广义表的深度
对于带头节点的广义表g,广义表深度的递归定义是它等于所有子表中表的最大深度加1。若g为原子,其深度为0。
求广义表深度的递归模型f()如下:、
代码
int GLDepth(GLNode *g) //求带头节点的广义表g的深度 { int max=0,dep; if (g->tag==0) return 0; //为原子时返回0 g=g->hp; //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->tp; //使g指向下一个元素 } return(max+1); //返回表的深度 }