广义表总结

Posted 风等

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了广义表总结相关的知识,希望对你有一定的参考价值。

最近复习考研数组和广义表总结。
什么是广义表
广义表的定义
线性表 线性表指的是n≥0个元素a1, a2, a3…的有序数列,并且线性表的元素具有原子性,即结构上是不可分割的一个整体。

广义表(Generalized list) 而广义表则是线性表的一种扩展延伸。相对于线性表,广义表最大的特点在于其元素既可以是一个确定的类型,同时也可以是另一个有不定数量的元素组成的表(广义表)。
不难看出从广义表的定义是递归的。广义表是线性表的递归数据结构。

广义表简称表,它是线性表的推广。一个广义表是n(n≥0)个元素的一个序列,若n=0时则称为空表。

设ai为广义表的第i个元素,则广义表GL的一般表示与线性表相同:

        GL=(a1,a2,…,ai,…,an) 

其中n表示广义表的长度,即广义表中所含元素的个数,n≥0。如果ai是单个数据元素,则ai是广义表GL的原子;如果ai是一个广义表,则ai是广义表GL的子表。

广义表具有如下重要的特性:
(1)广义表中的数据元素有相对次序;
(2)广义表的长度定义为最外层包含元素个数;
(3)广义表的深度定义为所含括弧的重数。其中原子的深度为0,空表的深度为1;
(4)广义表可以共享;一个广义表可以为其他广义表共享;这种共享广义表称为再入表;
(5)广义表可以是一个递归的表。一个广义表可以是自已的子表。这种广义表称为递归表。递归表的深度是无穷值,长度是有限值;

(6)任何一个非空广义表GL均可分解为表头head(GL) = a1和表尾tail(GL) = ( a2,…,an) 两部分。

广义表的基本概念
广义表的表示
我们通常可以用 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; //ATOM0:表示原子,LIST1:表示子表
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;
//ATOM0:表示原子,LIST1:表示子表
Typedef struct GLNode {
ElemTag tag; //公共部分,用以区分原子部分和表结点
union { //原子部分和表结点的联合部分
AtomType atom; //原子结点的值域
struct GLNode *hp; //表结点的表头指针
};
struct GLNode *tp;
//相当于线性链表的next,指向下一个元素结点
} *Glist; //广义表类型Glist 是一种扩展的线性链表

例子
同样我们画一下结构图

广义表的计算(以第二种存储结构为例)
广义表长度的计算(类似于链表的长度,直接统计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->tag0) 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); //返回表的深度
}

以上是关于广义表总结的主要内容,如果未能解决你的问题,请参考以下文章

数据结构22:数组和广义表

第四章_串数组和广义表_学习小结

广义表

数据结构——广义表

数据结构:广义表转置

数据结构第四章总结