【概念】
广义表具有以下重要的特性:
- 广义表中的数据元素是有相对次序的。
- 广义表的长度定义为最外层包含元素的个数。
- 广义表的深度定义为所含括弧的重数,其中原子的深度为0,空表的深度为1。
- 广义表可以共享,一个广义表可以被其他广义表共享,这种共享广义表称为再入表。
- 广义表可以是一个递归的表,一个广义表可以是自己的子表,这种广义表称为递归表。递归表的深度是无穷值,而长度是有限值。
【广义表的头尾链表存储表示】
广义表是一种递归的数据结构,因此很难为每个广义表分配固定大小的存储空间,所以其存储结构只好采用链式存储结构。
- 一类是表结点,用来表示广义表项,由标志域、表头指针域、表尾指针域组成;
- 另一类是原子结点,用来表示原子项,由标志域、原子的值域组成。
/* 广义表的头尾链表存储表示 */
typedef enum{ Atom, List }ElemTag; //Atom==0原子结点,List==1表结点
typedef char AtomType; //原子类型
typedef struct GLNode
{
ElemTag tag; //公共部分,用于区分原子结点和表结点
union //原子结点和表结点的联合部分
{
AtomType atom; //atom是原子结点的值域,AtomType由用户定义
struct
{
struct GLNode *hp; //指向表头
struct GLNode *tp; //指向表尾
}ptr; //表结点的指针域
}Union;
}GLNode;
typedef GLNode* GList; //广义表类型
这种结构求广义表的长度、深度、表头、表尾的操作十分方便。对于上述存储结构,若广义表为空,表头指针为空;否则,表头指针总是指向一个表结点,其中hp
指向广义表的表头结点 (或为原子结点、或为表结点) ,tp
指向广义表的表尾 (表尾为空时,指针为空,否则必为表结点)。
例题1:
例题2:
【广义表的扩展线性链表存储表示】
上述存储结构表结点太多,造成空间浪费。为了使表结点和原子结点既能在形式上保持一致,又能进行区别,可采用以下结构:.
/* 广义表的扩展线性链表存储表示 */
typedef enum { Atom, List }ElemTag; //Atom==0原子结点,List==1表结点
typedef char AtomType; //原子类型
typedef struct GLNode
{
ElemTag tag; //公共部分,用于区分原子结点和表结点
union //原子结点和表结点的联合部分
{
AtomType atom; //原子结点值域
struct GLNode *hp; //表结点的表头指针
}Union;
struct GLNode *tp; //相当于线性链表的next,指向下一个元素结点
}GLNode;
typedef GLNode* GList; //广义表类型