赞
踩
广义表是n个数据元素(d1,d2,d3,…,dn)的有限序列,di 既可以是单个元素,也可以是一个广义表。通常记作GL =(d1,d2,d3,…,dn),n是广义表长度。若其中 di 是一个广义表,则称 di 是广义表GL的子表。在广义表GL中,d1是广义表表头,其余部分组成的表称为广义表表尾。
例如:
D=():空表,长度为0。
A=(a,(b,c)):表长度为2的广义表,第一个元素是单个数据a,第二个元素是一个子表(b,c)。
B=(A,A,D):长度为3的广义表,前两个元素为表A,第三个元素为空表D。
C=(a,C):长度为2递归定义的广义表,C相当于无穷表C=(a,(a,(a,(…))))。
① 广义表的元素可以是子表,而子表还可以是子表,因此广义表是一个多层的结构。
② 广义表可以被其它广义表共享。如广义表B共享表A,在表B中不必列出表A的内容,只要通过子表的名称就可以引用该表。
③ 广义表具有递归性,如广义表C。
广义表中的每一个元素用一个结点来表示,表中有两类结点:一类是单个元素结点,即原子结点;另一类是子表结点,即表结点。任何一个非空的广义表都可以将其分解成表头和表尾两部分,反之,一对确定的表头和表尾可以唯一地确定一个广义表。因此,一个表结点可由三个域构成:标志域、指向表头的指针域和指向表尾的指针域,而元素结点只需要两个域:标志域和值域。
代码
/*广义表的头尾链表存储结构*/
typedef enum { ATOM, LIST }ElemTag; //ATOM=0,表示原子;LIST=1,表示子表
typedef struct GLNode {
ElemTag tag; //标志位tag用来区分原子结点和表结点
union {
int atom; //原子结点的值域
struct {
struct GLNode* hp, * tp //表结点的指针域htp,包括表头指针域hp和表尾指针域tp
}htp;
}atom_htp; //atom_htp是原子结点的值域atom和表结点的指针域htp的联合体域
}GLNode, * GList;
原子结点和表结点均由三个域构成。
代码
/*广义表的同层结点链存储结构*/
typedef enum { ATOM, LIST }ElemTag; //ATOM=0,表示原子;LIST=1,表示子表
typedef struct GLNode {
ElemTag tag; //标志位tag用来区分原子结点和表结点
union {
int atom; //原子结点的值域
struct GLNode* hp; //表头指针域
}atom_hp; //atom_hp是原子结点的值域atom和表结点的表头指针域hp的联合体域
struct GLNode* tp; //同层下一个结点的指针域
}GLNode, * GList;
/*求广义表L的表头,并返回表头指针*/ GList Head(GList L) { if (L == NULL) //空表无表头 return NULL; if (L->tag == ATOM) //原子不是表 exit(0); else return L->atom_htp.htp.hp; //返回表头指针 } /*求广义表L的表尾,并返回表尾指针*/ GList Tail(GList L) { if (L == NULL) //空表无表尾 return NULL; if (L->tag == ATOM) //原子不是表 exit(0); else return L->atom_htp.htp.tp; //返回表尾指针 }
/*求广义表长度*/ int Length(GList L) { int k = 0; GLNode* s; if (L == NULL) return 0; //空表长度为0 if (L->tag == ATOM) //原子不是表 exit(0); s = L; while (s != NULL) { //统计最上层表的长度 k++; s = s->atom_htp.htp.tp; } return k; } /*求广义表的深度*/ int Depth(GList L) { int d, max; GLNode* s; if (L == NULL) return 1; //空表深度为1 if (L->tag == ATOM) return 0; //原子深度为0 s = L; while (s != NULL) { //求每个子表的深度的最大值 d = Depth(s->atom_htp.htp.hp); if (d > max) max = d; s = s->atom_htp.htp.tp; } return (max + 1); //表的深度等于最深子表的深度+1 }
/*统计广义表中原子结点数目*/
int CountAtom(GList L) {
int n1, n2;
if (L == NULL)
return 0; //空表中没有原子
if (L->tag == ATOM)
return 1; //L指向单个原子
n1 = CountAtom(L->atom_htp.htp.hp); //统计表头中的原子数目
n2 = CountAtom(L->atom_htp.htp.tp); //统计表尾中的原子数目
return (n1 + n2);
}
/*复制广义表*/ int CopyGList(GList S, GList* T) { if (S == NULL) { //复制空表 *T = NULL; return OK; } *T = (GLNode*)malloc(sizeof(GLNode)); if (*T == NULL) return ERROR; (*T)->tag = S->tag; if (S->tag == ATOM) (*T)->atom_htp.atom = S->atom_htp.atom; //复制单个原子 else { /*复制表头*/ CopyGList(S->atom_htp.htp.hp, &((*T)->atom_htp.htp.hp)); /*复制表尾*/ CopyGList(S->atom_htp.htp.tp, &((*T)->atom_htp.htp.tp)); } return OK; }
参考:耿国华《数据结构——用C语言描述(第二版)》
更多数据结构内容关注我的《数据结构》专栏:https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。