引言
在学习数据结构的时候,在广义表这一节花了比较多的时间。广义表是一种递归数据类型的数据结构,平常编程用递归比较少,对递归比较陌生。所以广义表的难度就在于,如何实现递归求解。
其结构如图:
广义表在C中的数据结构
typedef struct lnode
{
int tag; //结点类型的标识
union //C语言的共用体数据类型
{
ElemType data; //原子结点的值
struct lnode *sublist; //指向子表的指针
}
struct lnode *link; //指向兄弟结点
}GLNode;
接下来是相关运算的代码实现部分
广义表基本运算:
1.求广义表的长度
思路:按照广义表长度的定义,形象的说表头的所有儿子结点个数,就是广义表的长度。
每个表及其儿子结点可以看做是一个线性表。其兄弟之间通过link指针连接。
所以从头结点的第一个儿子开始,一直到最后一个最小的儿子结束。儿子可以是表也可以是原子。
int GLLength(GLNode *g)
{
int n=0;
GLNode *g1=g->val.sublist;
while(g1!=NULL)
{
n++;
g1=g1->link;
}
return n;
}
2.求广义表的深度
思路:
可以将其类比于家族树,如果要问这个家族有多少代人。最正常的想法是从最低的那一层,也就是最晚出生的人开始,往上数直至最初的长辈。即要求最深(多少代人),并不是从根结点(最初的长辈)开始数。这符合递归的思想:自顶向下划分问题,自下而上解决问题。
所以,要求广义表的深度:求出表头的所有儿子中拥有最大深度的那个儿子。并在返回的时候+1,因为自身也算一个深度。
即:
GLDepth(g)=MAX{GLDepth(g的大孩子),GLDepth(g的二孩子),…,GLDepth(g的最后一个孩子)} + 1。
递归出口:
(1)遇到空表(g->val.sublist==NULL),直接返回1。(可以把原子结点类比于女儿,因为女儿生出的孩子不跟女方姓,所以只要是碰到女儿结点,就返回1)
(2)遇到原子结点,直接返回0。(类似于,家族中有着和人一样贵重的物品,被载入族谱,被当时的祖辈当成孩子一样重要,所以和孩子结点为兄弟关系,但是物体不具有繁衍的能力,所以它不具有深度)
int GLDepth(GLNode *g)
{
int maxdepth=0,depth;
if(g->tag==0) //为原子结点
return 0;
GLNode *g1=g->val.sublist; //找到第一个子结点
if(g1==NULL)
return 1;
while(g1!=NULL)
{
if(g1->tag==1)
{
depth=GLDepth(g1);
if(depth>maxdepth)