**广义表**（英語：）是一种非线性的数据结构。但如果广义表的每个元素都是原子，它就变成了线性表。广义表广泛地用于人工智能等领域的LISP语言。

**广义表**一般记作 LS = (a1, a2, ···, an), n是它的长度，ai可以是单个元素(原子)，也可以是广义表(子表)，当广义表非空时，称第一个元素a1为LS的表头，称其余元素组成的表为LS的表尾。注意：表头是元素(可以是原子，也可以是广表)，表尾一定是广义表。E=(a, E)是一个递归的表。D=(( ),(e),(a,(b,c,d)))是多层次的广义表，长度为3，深度为3。例：((a),a)的表头是(a)，表尾是(a)，((a))的表头是(a)，表尾是( )。

头尾链表存储表示
--------

### 存储结构

```
// 广义表的头尾链表存储表示
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是表结点的指针域，prt.hp和ptr.tp分别指向表头和表尾
 } a;
} \*GList, GLNode; // 广义表类型

```

### 基本操作

```
// 广义表的头尾链表存储的基本操作(11个)
#include"func5-1.c"
void InitGList(GList \*L) {
 // 创建空的广义表L
 \*L = NULL;
}

void CreateGList(GList \*L, SString S) {
 // 采用头尾链表存储结构，由广义表的书写形式串S创建广义表L。设emp="()"
 SString sub, hsub, emp;
 GList p, q;
 StrAssign(emp, "()"); // 空串emp="()"
 if (!StrCompare(S, emp)) // S="()"
 \*L = NULL; // 创建空表
 else { // S不是空串
 \*L = (GList)malloc(sizeof(GLNode));
 if (!\*L) // 建表结点
 exit(OVERFLOW);
 if (StrLength(S) == 1) {
 // S为单原子，只会出现在递归调用中
 (\*L)->tag = ATOM;
 (\*L)->a.atom = S[1]; // 创建单原子广义表
 } else { // S为表
 (\*L)->tag = LIST;
 p = \*L;
 SubString(sub, S, 2, StrLength(S) - 2);
 // 脱外层括号(去掉第1个字符和最后1个字符)给串sub
 do {
 // 重复建n个子表
 sever(sub, hsub); // 从sub中分离出表头串hsub
 CreateGList(&p->a.ptr.hp, hsub);
 q = p;
 if (!StrEmpty(sub)) { // 表尾不空
 p = (GLNode \*)malloc(sizeof(GLNode));
 if (!p)
 exit(OVERFLOW);
 p->tag = LIST;
 q->a.ptr.tp = p;
 }
 } while (!StrEmpty(sub));
 q->a.ptr.tp = NULL;
 }
 }
}
void DestroyGList(GList \*L) {
 // 销毁广义表L
 GList q1, q2;
 if (\*L) {
 if ((\*L)->tag == LIST) { // 删除表结点
 q1 = (\*L)->a.ptr.hp; // q1指向表头
 q2 = (\*L)->a.ptr.tp; // q2指向表尾
 DestroyGList(&q1); // 销毁表头
 DestroyGList(&q2); // 销毁表尾
 }
 free(\*L);
 \*L = NULL;
 }
}

void CopyGList(GList \*T, GList L) {
 // 采用头尾链表存储结构，由广义表L复制得到广义表T
 if (!L) // 复制空表
 \*T = NULL;
 else {
 \*T = (GList)malloc(sizeof(GLNode));
 // 建表结点
 if (!\*T)
 exit(OVERFLOW);
 (\*T)->tag = L->tag;
 if (L->tag == ATOM)
 (\*T)->a.atom = L->a.atom; // 复制单原子
 else {
 CopyGList(&((\*T)->a.ptr.hp), L->a.ptr.hp);
 // 递归复制子表
 CopyGList(&((\*T)->a.ptr.tp), L->a.ptr.tp);
 }
 }
}

int GListLength(GList L) {
 /\* 返回广义表的长度，即元素个数 \*/
 int len = 0;
 while (L) {
 L = L->a.ptr.tp;
 len++;
 }
 return len;
}

int GListDepth(GList L) {
 /\* 采用头尾链表存储结构，求广义表L的深度。\*/
 int max, dep;
 GList pp;
 if (!L)
 return 1; /\* 空表深度为1 \*/
 if (L->tag == ATOM)
 return 0; /\* 原子深度为0，只会出现在递归调用中 \*/
 for (max = 0, pp = L; pp; pp = pp->a.ptr.tp) {
 dep = GListDepth(pp->a.ptr.hp); /\* 递归求以pp->a.ptr.hp为头指针的子表深度 \*/
 if (dep > max)
 max = dep;
 }
 return max + 1; /\* 非空表的深度是各元素的深度的最大值加1 \*/
}

Status GListEmpty(GList L) {
 /\* 判定广义表是否为空 \*/
 if (!L)
 return TRUE;
 else
 return FALSE;
}

GList GetHead(GList L) {
 /\* 生成广义表L的表头元素，返回指向这个元素的指针 \*/
 GList h, p;
 if (!L) /\* 空表无表头 \*/
 return NULL;
 p = L->a.ptr.hp; /\* p指向L的表头元素 \*/
 CopyGList(&h, p); /\* 将表头元素复制给h \*/
 return h;
}

GList GetTail(GList L) {
 /\* 将广义表L的表尾生成为广义表，返回指向这个新广义表的指针 \*/
 GList t;
 if (!L) /\* 空表无表尾 \*/
 return NULL;
 CopyGList(&t, L->a.ptr.tp); /\* 将L的表尾拷给t \*/
 return t;
}

void InsertFirst\_GL(GList \*L, GList e) {
 /\* 初始条件：广义表存在。操作结果：插入元素e(也可能是子表)作为广义表L的第1元素(表头) \*/
 GList p = (GList)malloc(sizeof(GLNode)); /\* 生成新结点 \*/
 if (!p)
 exit(OVERFLOW);
 p->tag = LIST; /\* 结点的类型是表 \*/
 p->a.ptr.hp = e; /\* 表头指向e \*/
 p->a.ptr.tp = \*L; /\* 表尾指向原表L \*/
 \*L = p; /\* L指向新结点 \*/
}

void DeleteFirst\_GL(GList \*L, GList \*e) {
 // 初始条件：广义表L存在。操作结果：删除广义表L的第一元素，并用e返回其值
 GList p = \*L; // p指向第1个结点
 \*e = (\*L)->a.ptr.hp; // e指向L的表头
 \*L = (\*L)->a.ptr.tp; // L指向原L的表尾
 free(p); // 释放第1个结点
}

void Traverse\_GL(GList L, void(\*v)(AtomType)) {
 // 利用递归算法遍历广义表L
 if (L) // L不空
 if (L->tag == ATOM) // L为单原子
 v(L->a.atom);
 else { // L为广义表
 Traverse\_GL(L->a.ptr.hp, v);
 // 递归遍历L的表头
 Traverse\_GL(L->a.ptr.tp, v);
 // 递归遍历L的表尾
 }
}

```

扩展线性链表存储表示
----------

### 存储结构

```
// 广义表的扩展线性链表存储表示
typedef enum {ATOM, LIST} ElemTag;
// ATOM==0：原子，LIST==1：子表
typedef struct GLNode1 {
 ElemTag tag;
 // 公共部分，用于区分原子结点和表结点
 union {
 // 原子结点和表结点的联合部分
 AtomType atom; // 原子结点的值域
 struct GLNode1 \*hp; // 表结点的表头指针
 } a;
 struct GLNode1 \*tp;
 // 相当于线性链表的next，指向下一个元素结点
} \*GList1, GLNode1;
// 广义表类型GList1是一种扩展的线性链表

```

### 基本操作

```
// 广义表的扩展线性链表存储(的基本操作(13个)
#include"func5-1.c"

void InitGList(GList1 \*L) {
 // 创建空的广义表L
 \*L = NULL;
}

void CreateGList(GList1 \*L, SString S) {
 // 采用扩展线性链表存储结构，由广义表的书写形式串S创建广义表L。设emp="()"
 SString emp, sub, hsub;
 GList1 p;
 StrAssign(emp, "()"); /\* 设emp="()" \*/
 \*L = (GList1)malloc(sizeof(GLNode1));
 if (!\*L) /\* 建表结点不成功 \*/
 exit(OVERFLOW);
 if (!StrCompare(S, emp)) { /\* 创建空表 \*/
 (\*L)->tag = LIST;
 (\*L)->a.hp = (\*L)->tp = NULL;
 } else if (StrLength(S) == 1) { /\* 创建单原子广义表 \*/
 (\*L)->tag = ATOM;
 (\*L)->a.atom = S[1];
 (\*L)->tp = NULL;
 } else { /\* 创建一般表 \*/
 (\*L)->tag = LIST;
 (\*L)->tp = NULL;
 SubString(sub, S, 2, StrLength(S) - 2);
 // 脱外层括号(去掉第1个字符和最后1个字符)给串sub
 sever(sub, hsub); // 从sub中分离出表头串hsub
 CreateGList(&(\*L)->a.hp, hsub);
 p = (\*L)->a.hp;
 while (!StrEmpty(sub)) { // 表尾不空，则重复建n个子表
 sever(sub, hsub); // 从sub中分离出表头串hsub
 CreateGList(&p->tp, hsub);
 p = p->tp;
 };
 }
}

void DestroyGList(GList1 \*L) {
 /\* 初始条件：广义表L存在。操作结果：销毁广义表L \*/
 GList1 ph, pt;
 if (\*L) { /\* L不为空表 \*/
 /\* 由ph和pt接替L的两个指针 \*/
 if ((\*L)->tag) /\* 是子表 \*/
 ph = (\*L)->a.hp;
 else /\* 是原子 \*/
 ph = NULL;
 pt = (\*L)->tp;
 DestroyGList(&ph); /\* 递归销毁表ph \*/
 DestroyGList(&pt); /\* 递归销毁表pt \*/
 free(\*L); /\* 释放L所指结点 \*/
 \*L = NULL; /\* 令L为空 \*/
 }
}

void CopyGList(GList1 \*T, GList1 L) {
 /\* 初始条件：广义表L存在。操作结果：由广义表L复制得到广义表T \*/
 \*T = NULL;
 if (L) { /\* L不空 \*/
 \*T = (GList1)malloc(sizeof(GLNode1));
 if (!\*T)
 exit(OVERFLOW);
 (\*T)->tag = L->tag; /\* 复制枚举变量 \*/
 if (L->tag == ATOM) /\* 复制共用体部分 \*/
 (\*T)->a.atom = L->a.atom; /\* 复制单原子 \*/
 else
 CopyGList(&(\*T)->a.hp, L->a.hp); /\* 复制子表 \*/
 if (L->tp == NULL) /\* 到表尾 \*/
 (\*T)->tp = L->tp;
 else
 CopyGList(&(\*T)->tp, L->tp); /\* 复制子表 \*/
 }
}

int GListLength(GList1 L) {
 /\* 初始条件：广义表L存在。操作结果：求广义表L的长度，即元素个数 \*/
 int len = 0;
 GList1 p = L->a.hp; /\* p指向第1个元素 \*/
 while (p) {
 len++;
 p = p->tp;
 };
 return len;
}

int GListDepth(GList1 L) {
 /\* 初始条件：广义表L存在。操作结果：求广义表L的深度 \*/
 int max, dep;
 GList1 pp;
 if (L == NULL || L->tag == LIST && !L->a.hp)
 return 1; /\* 空表深度为1 \*/
 else if (L->tag == ATOM)
 return 0; /\* 单原子表深度为0，只会出现在递归调用中 \*/
 else /\* 求一般表的深度 \*/
 for (max = 0, pp = L->a.hp; pp; pp = pp->tp) {
 dep = GListDepth(pp); /\* 求以pp为头指针的子表深度 \*/
 if (dep > max)
 max = dep;
 }
 return max + 1; /\* 非空表的深度是各元素的深度的最大值加1 \*/
}

Status GListEmpty(GList1 L) {
 /\* 初始条件：广义表L存在。操作结果：判定广义表L是否为空 \*/
 if (!L || L->tag == LIST && !L->a.hp)
 return OK;
 else
 return ERROR;
}

GList1 GetHead(GList1 L) {
 /\* 生成广义表L的表头元素，返回指向这个元素的指针 \*/
 GList1 h, p;
 if (!L || L->tag == LIST && !L->a.hp) /\* 空表无表头 \*/
 return NULL;
 p = L->a.hp->tp; /\* p指向L的表尾 \*/
 L->a.hp->tp = NULL; /\* 截去L的表尾部分 \*/
 CopyGList(&h, L->a.hp); /\* 将表头元素复制给h \*/
 L->a.hp->tp = p; /\* 恢复L的表尾(保持原L不变) \*/
 return h;
}

GList1 GetTail(GList1 L) {
 // 将广义表L的表尾生成为广义表，返回指向这个新广义表的指针
 GList1 t, p;
 if (!L || L->tag == LIST && !L->a.hp) // 空表无表尾
 return NULL;
 p = L->a.hp; // p指向表头
 L->a.hp = p->tp; // 在L中删去表头
 CopyGList(&t, L); // 将L的表尾拷给t
 L->a.hp = p; // 恢复L的表头(保持原L不变)
 return t;
}

void InsertFirst\_GL(GList1 \*L, GList1 e) {
 // 初始条件：广义表存在。操作结果：插入元素e(也可能是子表)作为广义表L的第1元素(表头)
 GList1 p = (\*L)->a.hp;
 (\*L)->a.hp = e;
 e->tp = p;
}

void DeleteFirst\_GL(GList1 \*L, GList1 \*e) {
 // 初始条件：广义表L存在。操作结果：删除广义表L的第一元素，并用e返回其值
 if (\*L && (\*L)->a.hp) {
 \*e = (\*L)->a.hp;
 (\*L)->a.hp = (\*e)->tp;
 (\*e)->tp = NULL;
 } else
 \*e = \*L;
}

void Traverse\_GL(GList1 L, void(\*v)(AtomType)) {
 // 利用递归算法遍历广义表L
 GList1 hp;
 if (L) { // L不空
 if (L->tag == ATOM) { // L为单原子
 v(L->a.atom);
 hp = NULL;
 } else // L为子表
 hp = L->a.hp;
 Traverse\_GL(hp, v);
 Traverse\_GL(L->tp, v);
 }
}

```

参考资料
----

1. ↑  崔巍; 何玉洁; 郁红英.. 清华大学出版社. 2005: P59. ISBN 9787302103769.  使用`|accessdate=`需要含有`|url=` (帮助)