广义表(C++实现)

广义表是非线性结构,其定义是递归的。

以下给出几种简单的广义表模型:

wKioL1cU06LDp3cZAAAGadRgppI798.png

wKiom1cU0uWjiRe8AAAM3dKYxa8731.png

wKioL1cU06PCYs3lAAAm-7A2avQ633.png

由上图我们可以看到,广义表的节点类型无非head、value、sub三种,这里设置枚举类型,利用枚举变量来记录每个节点的类型:

enum  Type
{
    HEAD,   //头节点
    VALUE,  //值节点
    SUB,    //子表节点
};

  

每个节点都有自己的类型以及next指针,除此之外,如果该节点是VALUE类型还要分配空间存储该节点的有效值;但是若该节点是SUB类型,就需定义一个指针指向子表的头。

这里我们可以用联合来解决这个问题。

(联合(或共同体)是一种不同数据类型成员之间共享存储空间的方法,并且联合体对象在同一时间只能存储一个成员值)

构造节点

struct GeneralizedNode
{
    Type _type;       //  1.类型
    GeneralizedNode* _next;  //2.指向同层的下一个节点
    union
    {
        char _value;    //  3.有效值
        GeneralizedNode* _subLink;     // 3.指向子表的指针
    };
     
    GeneralizedNode(Type type = HEAD, char value = '0')
    :_value(value)
    ,_type(type)
    , _next(NULL)
    {
        if (_type == SUB)
        {
            _subLink = NULL;
        }
    }
};

 

广义表的定义及基本操作

class Generalized
{
public:
    //无参的构造函数,建立空的广义表
    Generalized();
    //建造广义表,有参数的构造函数
    Generalized(const char* str);
    //打印广义表
    void Print();
    //获取值节点的个数
    size_t Amount();
    //获取广义表的深度
    size_t Depth();
    //拷贝构造
    Generalized(const Generalized& g);
    赋值运算符的重载
    Generalized& operator=(const Generalized& g);
    析构函数
    ~Generalized();
 
protected:
    void _Print(GeneralizedNode* head);
    GeneralizedNode* _CreatList(const char*& str);
    size_t _Amount(GeneralizedNode* head);
    GeneralizedNode* _Copy(GeneralizedNode* head);
    void _Destory(GeneralizedNode* head);
protected:
    GeneralizedNode* _head;   //记录广义表头指针
};

 

 初始化建立广义表进行循环递归。遍历字符串时遇到字符就建立值节点,遇到'('就进行递归并建立子表;遇到')'就结束当前子表的建立,并返回当前子表的头指针。

    GeneralizedNode* _CreatList(const char*& str)
    {
        assert(*str == '(');
        GeneralizedNode* head = new GeneralizedNode(HEAD,'0');
        GeneralizedNode* cur = head;
        str++;
        while (str != '\0')
        {
            if ((*str >= '0'&&*str <= '9') || (*str >= 'a'&&*str <= 'z') || (*str >= 'A'&&*str <= 'Z'))
            {
                cur->_next = new GeneralizedNode(VALUE, *str);
                cur = cur->_next;
            }
            else if (*str == '(')
            {
                cur->_next = new GeneralizedNode(SUB);
                cur = cur->_next;
                cur->_subLink = _CreatList(str);
            }
            else if (*str == ')')
            {
                return head;
            }
            str++;
        }
        return head;
    }

 

 打印广义表:当节点的类型为SUB时进行递归,最后不要忘了每打印完一层要打印一个后括号。

    void _Print(GeneralizedNode* head)
    {
        if (head == NULL)
        {
            cout << "Generalized table is NULL" << endl;
            return;
        }
        GeneralizedNode* cur = head;
        while (cur)
        {
            if (cur->_type == HEAD)
            {
                cout << '(';
            }
            else if (cur->_type == VALUE)
            {
                cout << cur->_value;
                if (cur->_next)
                {
                    cout << ',';
                }
            }
            else if (cur->_type == SUB)
            {
                _Print(cur->_subLink);
                if (cur->_next)
                {
                    cout << ',';
                }              
            }
            cur = cur->_next;
        }
        cout << ')';
    }

  

获取值节点的个数:设置count变量,遇到值节点就加1,遇到SUB节点进行递归并将返回值加给count

    size_t _Amount(GeneralizedNode* head)
    {
        GeneralizedNode* begin = head;
        size_t count = 0;
        while (begin)
        {
            if (begin->_type == VALUE)
            {
                count++;
            }
            if (begin->_type == SUB)
            {
                count += _Amount(begin->_subLink);
            }
            begin = begin->_next;
        }
        return count;
    }

  

广义表的深度:设置变量dp和max分别用来记录当前子表即当前SUB节点指向的子表深度,以及本层所有的SUB节点中深度最大的子表的深度。

    size_t _Depth(GeneralizedNode* head)
    {
        if (_head == NULL)
        {
            return 0;
        }
        size_t dp=0;
        GeneralizedNode* cur = head;
        size_t max = 0;
        while (cur)
        {
            if (cur->_type == SUB)
            {
                dp=_Depth(cur->_subLink);
                if (max < dp)
                {
                    max = dp;
                }
            }
            cur = cur->_next;
        }
        return max+1;
    }

 

销毁广义表:依次遍历节点,遇到子表递归,将子表的节点delete完成后,再回到当前层继续遍历。

    void _Destory(GeneralizedNode* head)
    {
        if (head == NULL)
        {
            return;
        }
        while (head)
        {
            GeneralizedNode* begin = head->_next;
            if (head->_type == SUB)
            {
                _Destory(head->_subLink);
            }
            delete head;
            head = begin;
        }
    }

  广义表的拷贝构造及赋值运算符重载与构造函数的递归方式类似,这里就不再阐述冗余信息。

 

转载于:https://www.cnblogs.com/Lynn-Zhang/p/5429707.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值