广义表的创建,长度,深度和元素个数详解(C实现)

一、广义表操作思路

1.创建思路

typedef struct node
{
	int tag;					//用于识别单元素与子表
	union						//大括号中多选一
	{
		char data;				//单元素
		struct node *child;	//子表
	}val;
	struct node *next;			//指向下一个元素
}GLNode;

由图可看出,tag=1时,为子表的头结点,tag=0时,为子表元素;并且头结点有一个指向孩子结点的child指针,元素结点有一个指向兄弟结点的next指针。

那创建思路不就来了 

  • 先不考虑外面的括号,如果字符串不为结束符,就申请存储空间。
  • 如果字符为(,就说明进入一个新的子串,那就把标识符赋值1,然后递归创建它的孩子结点。
  • 如果字符为),就说名子串结束,将表置空。
  • 如果为正常字符,tag=0,孩子结点的数据=这个字符。
  • 如果字符等于 ‘ ,’,说明有另一个子串,递归创建它的兄弟指针。

创建思路还有一个是将串分解,用到String 类库的 个别函数。个人尝试过,有点复杂,最后没调试通,感兴趣的可以去看看广义表创建

2、遍历思路

  • 表不为空是大前提
  • 如果tag==0,说明是元素结点,输出值。
  • 如果为tag==1,说明进入子串了,所以输出(,并且递归遍历它的孩子结点,最后输出)。
  • 如果兄弟结点不为空,则输出‘  ,’,并且递归遍历它的兄弟结点。

二、代码实现

#include <stdio.h>  
#include <stdlib.h>  
  
typedef struct node {  
    int tag;  
    union {  
        char data;  
        struct node *child;  
    } val;  
    struct node *next;  
} GLNode;  
  
// 创建广义表  
GLNode *Create(const char **elem) {  
    if (!**elem) return NULL;  
  
    GLNode *L = (GLNode *)malloc(sizeof(GLNode));  
    if (!L) return NULL;  
  
    char c = **elem;  
    (*elem)++;  
  
    if (c == '(') {  
        L->tag = 1;  
        L->val.child = Create(elem);  
    } else if (c == ')') {  
        free(L); // 释放当前节点,因为')'意味着子表结束  
        return NULL;  
    } else {  
        L->tag = 0;  
        L->val.data = c;  
    }  
  
    L->next = Create(elem); // 继续处理兄弟节点  
    return L;  
}  
  
// 输出广义表  
void Print(GLNode *s) {  
    if (!s) return;  
  
    if (s->tag == 0) {  
        printf("%c", s->val.data);  
    } else {  
        printf("(");  
        Print(s->val.child);  
        printf(")");  
    }  
  
    if (s->next) {  
        printf(",");  
        Print(s->next);  
    }  
}  
  
// 求广义表长度  
int Getlength(GLNode *s) {  
    if (!s) return 0;  
    int len = Getlength(s->next); // 兄弟节点的长度  
    if (s->tag == 1) {  
        // 如果是子表,加上子表的长度(这里假设子表长度函数已定义,但这里直接递归调用Getlength)  
        len += 1 + Getlength(s->val.child); // 1代表子表本身  
    } else {  
        len += 1; // 原子节点长度为1  
    }  
    return len;  
}  
  
// 求深度  
int Getdepth(GLNode *s) {  
    if (!s) return 0;  
    int depth = 0;  
    if (s->tag == 1) {  
        depth = Getdepth(s->val.child) + 1;  
    }  
    int nextDepth = Getdepth(s->next);  
    if (nextDepth > depth) depth = nextDepth;  
    return depth;  
}  
  
// 求原子结点个数  
int Number(GLNode *s) {  
    if (!s) return 0;  
    int count = 0;  
    if (s->tag == 0) count++;  
    count += Number(s->val.child);  
    count += Number(s->next);  
    return count;  
}  
  
int main() {  
    char *str = "(a,(b,c,d))";  
    GLNode *L = Create(&str);  
    printf("广义表L为:");  
    Print(L);  
    printf("\n广义表的长度:");  
    printf("%d\n", Getlength(L));  
    printf("广义表的深度:");  
    printf("%d\n", Getdepth(L));  
    printf("广义表的元素个数为:");  
    printf("%d\n", Number(L));  
  
    // 释放内存(此处略过,实际使用时需要添加)  
    return 0;  
}

三、运行。

 搞了将近八个小时,大部分时间都用在对字符串进行分割的创建思路上,随后看看大神们写的,突然茅塞顿开,最重要的还是先明白广义表的存储结构,怎么运行的,其次在合理运用递归,还是能简单的搞出来的,代码可运行,需要的可复制。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

犀牛超人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值