/**********************
 
       WZ  ASUST 2016
表的实现与表头表尾问题
缺函数:找值
**********************/
#include<iostream>
#include<assert.h>
#include<string>
using namespace std;
 
//实现广义表的结构
// 节点的类型:来代替直接写3类 结构体
enum Type//枚举类型
{
    HEAD,
    VALUE,
    SUB,
};
 //构造节点:
struct GeneralizedNode
{
    Type _type;//类型
    GeneralizedNode* _next;//值相同层的下一个节点
    union//共用体/联合
    {
        int _value;//值节点
        GeneralizedNode* _SubLink;//指向字表的指针
    };
    GeneralizedNode();
    GeneralizedNode(Type type, int value); //全缺省构造函数
};
 //广义表的定义及基本操作:
class Generalized
{
public:
    Generalized();
    Generalized(const char* str);//构造
    Generalized(const Generalized& g);//拷贝构造
    Generalized& operator=(const Generalized& g);
    ~Generalized();
    void Print();
    size_t Size();
    size_t Depth();
protected:
    GeneralizedNode* _CreatList(const char*& str);
    GeneralizedNode* _Copy(GeneralizedNode* head);
    bool _isValue(char ch);//判断是否为字母或数字
    void _Distory(GeneralizedNode* head);
    void _Print(GeneralizedNode* head);
    size_t _Size(GeneralizedNode* head);
    size_t _Depth(GeneralizedNode* head);
protected:
    GeneralizedNode* _head;
};
 
GeneralizedNode::GeneralizedNode()
:_next(NULL)
{}
GeneralizedNode::GeneralizedNode(Type type, int value)
: _type(type)
, _next(NULL)
{
    if (_type == VALUE)
    {
        _value = value;
    }
    if (_type == SUB)
    {
        _SubLink = NULL;
    }
}
Generalized::Generalized()
:_head(NULL)
{}
Generalized::Generalized(const char* str)//构造函数
: _head(NULL)
{
    _head = _CreatList(str);
}
//初始化建立广义表进行循环递归。遍历字符串时遇到字符就建立值节点,遇到'('就进行递归并建立子表;遇到')'就结束当前子表的建立,并返回当前子表的头指针
GeneralizedNode* Generalized::_CreatList(const char*& str)
{//广义表:(a, (b, c))
    assert('(' == *str);
    str++;
    GeneralizedNode* head = new GeneralizedNode(HEAD, 0);//建立表的头结点
    GeneralizedNode* cur = head;
    while (str)
    {
        if (_isValue(*str))//*str为字母或数字
        {
            cur->_next = new GeneralizedNode(VALUE, *str);//建立value结点
            cur = cur->_next;
            str++;
        }
        else if (*str == '(')//如果为(,则出现字表,进行递归调用
        {
            GeneralizedNode* subNode = new GeneralizedNode(SUB, 0);//建立子表结点
            cur->_next = subNode;
            cur = cur->_next;
            subNode->_SubLink = _CreatList(str);//_SubLink指向子表构造子表
        }
        else if (*str == ')')//表示表的结束(包括子表),返回表的头结点
        {
            str++;
            return head;
        }
        else
        {
            str++;
        }
    }
    assert(false);
    return head;
}
bool Generalized::_isValue(char ch)//判断是否为字母或数字
{
    if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
    {
        return true;
    }
    return false;
}
Generalized::Generalized(const Generalized& g)//拷贝构造函数
{
    _head = _Copy(g._head);
}
GeneralizedNode* Generalized::_Copy(GeneralizedNode* head)
{
    GeneralizedNode* newhead = new GeneralizedNode(HEAD, 0);
    GeneralizedNode* cur = head;
    GeneralizedNode* newcur = newhead;
    while (cur)
    {
        if (cur->_type == VALUE)//cur._type为VALUE或SUB时建立结点,newcur才存在指向下一个结点
        {
            newcur->_next = new GeneralizedNode(VALUE, cur->_value);
            newcur = newcur->_next;
        }
        if (cur->_type == SUB)
        {
            newcur->_next= new GeneralizedNode(SUB, 0);
            newcur = newcur->_next;
            newcur->_SubLink = _Copy(cur->_SubLink);//递归调用_Copy进行复制
        }
        cur = cur->_next;
    }
    return newhead;
}
Generalized& Generalized::operator=(const Generalized& g)//传统写法
{
    if (this != &g)
    {
        GeneralizedNode* tmp = _Copy(g._head);
        _Distory(_head);
        _head = tmp;
    }
    return *this;
}
Generalized::~Generalized()
{
    _Distory(_head);
}
//销毁广义表:依次遍历节点,遇到子表递归,将子表的节点delete完成后,再回到当前层继续遍历。
void Generalized::_Distory(GeneralizedNode* head)
{
    GeneralizedNode* cur = head;
    while (cur)
    {
        GeneralizedNode* del = cur;
        if (cur->_type == SUB)
        {
            _Distory(cur->_SubLink);//释放cur结点的字表
        }
        cur = cur->_next;
        delete del;
    }
}
void Generalized::Print()
{
    _Print(_head);
    cout << endl;
}
//打印广义表:当节点的类型为SUB时进行递归,最后不要忘了每打印完一层要打印一个后括号。
void Generalized::_Print(GeneralizedNode* head)
{
    GeneralizedNode* cur = head;
    while (cur)
    {
        if (cur->_type == HEAD)
        {
            cout << "(";
        }
        if (cur->_type == VALUE)
        {
            cout << (char)cur->_value;//强转为char类型
            if (cur->_next)//如果cur->_next不为空打印“,”
                cout << ",";
        }
        if (cur->_type == SUB)
        {
            _Print(cur->_SubLink);
            if (cur->_next)
                cout << ",";
        }
        cur = cur->_next;
    }
    cout << ")";
}
size_t Generalized::Size()
{
    return _Size(_head);
}
//获取值节点的个数:设置count变量,遇到值节点就加1,遇到SUB节点进行递归并将返回值加给count
size_t Generalized::_Size(GeneralizedNode* head)
{
    GeneralizedNode* cur = head;
    size_t count = 0;
    while (cur)
    {
        if (cur->_type == VALUE)
        {
            ++count;
        }
        if (cur->_type == SUB)
        {
            count += _Size(cur->_SubLink);
        }
        cur = cur->_next;
    }
    return count;
}
//广义表的深度:设置变量 分别用来记录当前子表即当前SUB节点指向的子表深度,以及本层所有的SUB节点中深度最大的子表的深度。
size_t Generalized::Depth()
{
    return _Depth(_head);
}
size_t Generalized::_Depth(GeneralizedNode* head)
{
    GeneralizedNode* cur = head;
    size_t depth = 1;
    while (cur)
    {
        if (cur->_type == SUB)
        {
            size_t cdepth = _Depth(cur->_SubLink);
            if (cdepth + 1 > depth)//比较子表深度,保存较大的
            {
                depth = cdepth + 1;
            }
        }
        cur = cur->_next;
    }
    return depth;
}
int main()
{
    //Generalized g1("(a)");
    //Generalized g2("(a,b)");
    Generalized g3("(a,(c,d))");
    Generalized g4("(a,(b,(c),d),e)");
    Generalized g5 = g4;
    g5 = g3;
    //g1.Print();
    //g2.Print();
    g3.Print();
    g4.Print();
    g5.Print();
    cout << "g3.Size():" << g3.Size() << endl;
    cout << "g4.Size():" << g4.Size() << endl;
    cout << "g3.Depth():" << g3.Depth() << endl;
    cout << "g4.Depth():" << g4.Depth() << endl;
return 0;
}

viewfile?f=A2BCBF0427C89DDFE9B81DF1BF635

/*************************

除了表头即是表尾

有隐含的括号问题

************************/



viewfile?f=A2BCBF0427C89DDFE9B81DF1BF635