实现广义表的基本运算

/**
*    实验题目:
*        实现广义表的基本运算
*    实验目的:
*        领会广义表的链式存储结构及其基本算法设计
*    实验内容:
*        实现广义表的各种运算,设计一个程序,实现如下功能:
*    1、建立广义表g = "(b,(b,a,(#),d),((a,b),c,((#))))"的链式存储结构
*    2、输出广义表g的长度
*    3、输出广义表g的深度
*    4、输出广义表g的最大原子
*/

#include <stdio.h>
#include <malloc.h>

typedef struct lnode
{
    int tag; // 结点类型标识
    union
    {
        char data;
        struct lnode *sublist;
    }val;
    struct lnode *link; // 指向下一个元素
}GLNode; // 声明广义表结点类型

/*---------------返回由括号表示法表示s的广义表链式存储结构(递归方法)----------------*/
static GLNode *create_gl(char *&s)
{
    GLNode *g;
    char ch = *s++; // 取一个字符

    if(ch != '\0') // 串未结束判断
    {
        g = (GLNode *)malloc(sizeof(GLNode)); // 创建一个新结点
        if(ch == '(') // 当前字符为左括号时
        {
            g->tag = 1; // 新结点作为表头结点
            g->val.sublist = create_gl(s); // 递归构造子表并链到表头结点
        }
        else if(ch == ')') // 遇到右括号字符,g设置为空
        {
            g = NULL;
        }
        else if(ch == '#') // 遇到#字符,表示空表
        {
            g->val.sublist = NULL;
        }
        else // 为原子字符
        {
            g->tag = 0; // 新结点作为原子结点
            g->val.data = ch;
        }
    }
    else // 串结束,g设置为空
    {
        g = NULL;
    }

    ch = *s++; // 取下一个字符
    if(g != NULL) // 串未结束,继续构造兄弟结点
    {
        if(ch == ',') // 当前字符为逗号
        {
            g->link = create_gl(s); // 递归构造兄弟结点
        }
        else // 没有兄弟了,将兄弟指针设置为NULL
        {
            g->link = NULL;
        }
    }

    return g; // 返回广义表g
}

/*---------------输出广义表g----------------*/
static void disp_gl(GLNode *g)
{
    if(g != NULL) // 表非空判断
    {
        if(g->tag == 0) // g的元素为原子时
            printf("%c", g->val.data); // 输出原子值
        else // g的元素为子表时
        {
            printf("(");
            if(g->val.sublist == NULL) // 为空表时
                printf("#");
            else    // 为非空子表时
                disp_gl(g->val.sublist); // 递归输出子表
            printf(")");
        }
        if(g->link != NULL)
        {
            printf(",");
            disp_gl(g->link); // 递归输出g的兄弟
        }
    }
}

/*---------------求广义表g的长度----------------*/
static int gl_length(GLNode *g)
{
    int n = 0;

    g = g->val.sublist; // g指向广义表的第一个元素
    while(g != NULL)
    {
        n++;/*---------------求广义表g的最大原子----------------*/
        g = g->link;
    }

    return n;
}

/*---------------求广义表g的深度----------------*/
static int gl_depth(GLNode *g)
{
    int max_dep = 0;
    int dep;

    if(g->tag == 0)
        return 0;
    g = g->val.sublist; // g指向第一个元素
    if(g == NULL) // 为空表时返回1
        return 1;
    while(g != NULL) // 遍历表中的每一个元素
    {
        if(g->tag == 1) // 元素为子表的情况
        {
            dep = gl_depth(g); // 递归调用求出子表的深度
            if(dep > max_dep)
                max_dep = dep; // max_dep为同一层所求过的子表中深度的最大值
        }
        g = g->link; // g指向下一个元素
    }

    return (max_dep + 1); // 返回表的深度
}

/*---------------求广义表g的最大原子----------------*/
static char gl_max_atom(GLNode *g)
{
    char max1, max2;

    if(g != NULL)
    {
        if(g->tag == 0)
        {
            max1 = gl_max_atom(g->link);
            return (g->val.data > max1 ? g->val.data : max1);
        }
        else
        {
            max1 = gl_max_atom(g->val.sublist);
            max2 = gl_max_atom(g->link);
            return (max1 > max2 ? max1 : max2);
        }
    }
    else
        return 0;
}

/*---------------销毁广义表g----------------*/
static void destroy_gl(GLNode *&g)
{
    GLNode *g1, *g2;

    g1 = g->val.sublist; // g1指向广义表的第一个元素
    while(g1 != NULL) // 遍历所有元素
    {
        if(g1->tag == 0) // 若为原子结点
        {
            g2 = g1->link; // g2临时保存兄弟结点
            free(g1); // 释放g1所指原子结点
            g1 = g2; // g1指向后继兄弟结点
        }
        else // 若为子表
        {
            g2 = g1->link; // g2临时保存兄弟结点
            destroy_gl(g1); // 递归释放g1所指子表的空间
            g1 = g2; // g1指向后继兄弟结点
        }
    }
    free(g); // 释放头结点空间
}

int main(void)
{
    GLNode *g;
    char *str = "(b,(b,a,(#),d),((a,b),c,((#))))";

    g = create_gl(str);
    printf("广义表g:");
    disp_gl(g);
    printf("\n");
    printf("广义表g的长度:%d\n", gl_length(g));
    printf("广义表g的深度:%d\n", gl_depth(g));
    printf("广义表g的最大原子:%c\n", gl_max_atom(g));
    destroy_gl(g);

    return 0;
}
测试结果:

广义表g:(b,(b,a,((#)),d),((a,b),c,(((#)))))
广义表g的长度:3
广义表g的深度:4
广义表g的最大原子:d

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值