模拟实现广义表(详细注释)

来源:互联网 发布:网络狼人杀发言技巧 编辑:程序博客网 时间:2024/06/05 07:30


首先先来了解一下概念:

  广义表是非线性的结构,是线性表的一种扩展,是有n个元素组成有限序列。

  广义表的定义是递归的,因为在表的描述中又得到了表,允许表中有表。


再来一个图了解一下其数据结构




下来我们来代码实现一下

#pragma once#include <iostream>#include <assert.h>using namespace std;enum Type             //定义结点的类型{          HEAD,             //头结点VALUE,            //这个结点存储值SUB,              //即子结点};struct GeneralListNode      //结点的结构{ Type _type;             //结点的类型GeneralListNode* _next; //* _nextunion                   //共用体 结点里面不是存值就是子结点{char _value;GeneralListNode* _LinkNode;};GeneralListNode(Type type, char value = ' ') //这里需要写一个构造函数,在复制时候,碰到子结点就需要构造一个新的结点,所以有类型(SUB和VALUE),切需要一个缺省值:_type(type),_next(NULL)    //首先默认初始为下一个为没有结点 即是 NULL{if(_type == VALUE)    //共用体里面的类型{_value = value; }if(_type == SUB){_LinkNode = NULL;  //里面的子结点首先默认指向空}}};class GeneralList{typedef GeneralListNode Node; //这里为了方便,将广义表的结点定为Nodepublic:GeneralList()     //默认构造函数:_head(NULL){}GeneralList(const char* str) // 有初始化的构造函数:_head(NULL){_head = _CreateList(str);}GeneralList(const GeneralList& g)   //拷贝构造{_head = _Copy(g._head);}/*GeneralList& operator= (const GeneralList& g) //赋值操作符重载{if(this != &g)                   //判断是不是自己给自己赋值{Node* temp = Copy(g._head);  // 先拷贝一份if(_head!=NULL)              //这个不是空的话Destory(_head);          //删除 要赋值给对象的数据_head = temp;                //连接    }return *this;}                                    */GeneralList operator= (GeneralList g){std::swap(_head,g._head);         //交换他们的临时值return *this;              }~GeneralList(){if(_head)       //防止要析构的为空{Destory();}_head = NULL;}void Destory() //销毁函数{_Destory(_head);_head = NULL;}void Print()  //打印函数{_Print(_head);cout<<endl;}size_t Depth(){return _Depth(_head);}size_t Size(){return _Size(_head);}protected:size_t _Depth(Node* head){assert(head && head->_type == HEAD);size_t maxdepth = 1;size_t depth = 1;   // 有头的话 起码是一层深度Node* cur = head;while (cur){if (cur->_type == SUB){depth = _Depth(cur->_LinkNode); //子点的深度if(depth + 1 > maxdepth) //碰到一个新的SUB就有了一个新的深度 加一去比较{maxdepth = depth + 1; //更新一个}}cur = cur->_next;}return maxdepth;}size_t _Size(Node* head){assert(head && head->_type == HEAD);size_t count = 0;Node* cur = head;while(cur){if(cur->_type == VALUE){++count;}if(cur->_type == SUB){count += _Size(cur->_LinkNode);}cur = cur->_next;}return count;}void _Print(Node* head){assert(head && head->_type == HEAD);Node* cur = head;  //定义一个头开始打印cout<<"("; while (cur){if(cur->_type == HEAD){cur = cur->_next;   //判断三个类型}else if(cur->_type == VALUE){cout<<cur->_value;if(cur->_next){cout<<',';cur = cur ->_next;}else {return ;}}else if(cur->_type = SUB){_Print(cur->_LinkNode);cout<< ')';if(cur->_next){cout<<',';   //注意逗号位置要随每个类型后面cur = cur->_next;}else {break;}}}cout<<')';}void _Destory(Node* head){assert(head && head->_type == HEAD); //要需要判断是否为空和是否是个头才可以Node* cur = head;  //使头位置不变while(cur){if(cur->_type == SUB)  //当碰到新的节点需要递归{_Destory(cur->_LinkNode);}Node* del = cur;  //定义一个作为 删除 用cur = cur->_next;delete del;}}Node* _Copy(Node* head){Node* newhead = new Node(HEAD); // 创建一个HEAD类型的结点Node* tail = newhead;       // 新结点的头位置不变Node* cur = head->_next;   //所要拷贝数据 有效位置开始while (cur){if(cur->_type == VALUE){tail->_next  = new Node(VALUE, cur->_value);//传值tail = tail->_next;}else if(cur->_type = SUB){tail->_next = new Node(SUB);tail = tail->_next;  //知道了当前新创建的结点位置tail->_LinkNode = _Copy(cur->_LinkNode); //结点位置的结点去递归新的广义表}cur= cur->_next;}return newhead;}bool IsValue (char ch){if((ch >= '0' && ch<='9')||(ch>='a' && ch<='z')||(ch>='A' && ch<='Z')){return true;}return false;}Node* _CreateList(const char*& str)  //连接到构造结点部分 创建一个有初始值的结点  注意引用{assert(*str);++str;        //因为第一个结点是空的Node* head = new Node(HEAD); // 新构造了一个头结点(一个初始的类型)Node* cur = head;            //不要让头结点位置去改变while(*str)                  //开始读取广义表{if(*str == '(')     //“(”即是一个新结点的开始{Node* sub = new Node(SUB);  //创建一个SUB类型的结点cur->_next = sub;           //头一个结点的下一个结点 sub->_LinkNode = _CreateList(str);//是SUB类型,所以要去创建这个内容cur = cur->_next;                  // 后移               }else if (IsValue(*str))   //判断是否是 字符类型{Node* value = new Node(VALUE, *str); // 见构造str++;cur->_next = value;    //连接cur = cur->_next;      //后移}else if(*str == ')')  //其中的一个 ) 结束位置{str++;return head;       }else              //遇到空格,逗号等情况{ ++str;   }}return head;}protected:Node* _head;};
所有的公有实现在下pubilc函数 以提供接口,内部函数写在protected;


0 0
原创粉丝点击