//文件名:"GList.h" #pragma once #include <string> using namespace std; /* 广义表类 存储结构:1.头尾表示法;2.孩子兄弟表示法 */ /* 头尾表示法的链式存储结构 结构说明: 1.每个结点都看成是一个子表 2.以标志域区分结点类型:元素结点、表结点 3.表头指针指向表的第一个结点;表尾指针指向表的第二个结点 */ struct GLNode { int tag; //标志域:0|元素结点 1|表结点 //联合体 union { char data; //数据元素 struct atom { GLNode *hp, *tp; //表头、表尾指针 } ptr; //头尾指针域 }; }; class GList { private: GLNode * ls; //广义表头指针 string * s; //广义表字符串 int count; //所有结点计数 GLNode *_CreateGList(string *s, int *index = NULL); //创建广义表 bool _IsValue(char c); //判断字符是否为合法字符 void _Destory(GLNode *p); //销毁广义表 int _Depth(GLNode * p); //求广义表深度 GLNode *_Copy(GLNode *p); //复制广义表 int _NodeCount(GLNode *p); //结点数统计(子表结点、元素结点) string _ToString(GLNode *p); //内部接口:解析广义表为字符串 public: GList(); //无参构造 GList(string s); //有参构造,广义表字符串 ~GList(); //析构函数,销毁广义表 void Init(string s); //初始化广义表 int Length(); //求广义表长度 int Depth(); //求广义表深度 GList *Copy(); //赋值广义表 GList *GetHead(); //获取表头 GList *GetTail(); //获取表尾 string ToString(); //公共接口:解析广义表为字符串 };
//文件名:"GList_Test.cpp" #include "stdafx.h" #include <iostream> #include <string> #include "GList.h" using namespace std; int main() { string str1 = "()"; string str2 = "(a,b,(c,d),e)"; string str3 = "((a,b),c,(d),(e,f))"; string str4 = "((a,b),c,(d,(e,(f,g))),(h,i))"; GList *glist1 = new GList(str1); GList *glist2 = new GList(str2); GList *glist3 = new GList(str3); GList *glist4 = new GList(str4); cout << "glist1的广义表:" << glist1->ToString() << " 深度:" << glist1->Depth() << " 长度:" << glist1->Length() << endl; cout << "glist1的表头:" << ((glist1->GetHead() == NULL) ? "空" : (glist1->GetHead()->ToString())) << " 表尾:" << glist1->GetTail()->ToString() << endl; cout << "glist2的广义表:" << glist2->ToString() << " 深度:" << glist2->Depth() << " 长度:" << glist2->Length() << endl; cout << "glist2复制的广义表:" << glist2->Copy()->ToString() << endl; cout << "glist2的表头:" << glist2->GetHead()->ToString() << " 表尾:" << glist2->GetTail()->ToString() << endl; cout << "glist3的广义表:" << glist3->ToString() << " 深度:" << glist3->Depth() << " 长度:" << glist3->Length() << endl; cout << "glist3的表头:" << glist3->GetHead()->ToString() << " 表尾:" << glist3->GetTail()->ToString() << endl; cout << "glist4的表头:" << glist4->ToString() << " 深度:" << glist4->Depth() << " 长度:" << glist4->Length() << endl; delete glist1; delete glist2; delete glist3; delete glist4; return 0; }
//文件名:"GList.cpp" #include "stdafx.h" #include <iostream> #include "GList.h" using namespace std; GList::GList() { /* 构造器:无参 */ Init(""); } GList::GList(string s) { /* 构造器:构建广义表 */ Init(s); } GList::~GList() { /* 析构函数:销毁广义表 */ delete s; _Destory(this->ls); cout << "结点剩余数(子表+元素):" << this->count << endl; } void GList::Init(string s) { /* 初始化广义表 */ if (this->ls == NULL) { if (s != "") { this->count = 0; this->s = new string(s); this->ls = _CreateGList(this->s); cout << "结点总数(子表+元素):" << this->count << endl; } else { this->count = 0; this->s = NULL; this->ls = NULL; } } else return; } GLNode *GList::_CreateGList(string *s, int *index) { /* 递归创建广义表方法 参数: 1. string *s : 字符串广义表 2. int *index : 全局字符串索引 注:保持 s 和 index 内存地址不变 返回值: 1. 广义表子表结点指针 */ GLNode *SLNode = NULL, *ANode = NULL; //子表结点(包含单元素、多元素),元素结点 char var = '0'; //字符变量,初始化 '0' //初始化 索引为 0 if (index == NULL) index = new int(0); //字符串索引 *index 加1 向后移动 (*index)++; //遍历字符串 if(*index < (int)s->length()) { //获取索引处字符 var = s->at(*index); //1.1.如果字符是'(',则创建 多元素子表结点 if (var == '(') { //创建子表结点 SLNode = new GLNode(); SLNode->tag = 1; SLNode->ptr.hp = _CreateGList(s, index); //子表结点 hp 指向 表头(多元素子表) SLNode->ptr.tp = _CreateGList(s, index); //子表结点 tp 指向 表尾 this->count++; } //1.2.如果字符是')',则结束子表创建 else if (var == ')') { return NULL; } //1.3.如果字符是合法字符,则创建 单元素子表结点 else if (_IsValue(var)) { //创建元素结点 ANode = new GLNode(); ANode->tag = 0; ANode->data = var; //赋值 字符 //创建子表结点 SLNode = new GLNode(); SLNode->tag = 1; SLNode->ptr.hp = ANode; //子表结点 hp 指向元素结点,即单元素子表表头 SLNode->ptr.tp = _CreateGList(s, index); //子表结点 tp 指向 表尾 this->count += 2; } //1.4.其它字符,如:',',则直接进入下一个字符的子表创建 else { return _CreateGList(s, index); } } return SLNode; } bool GList::_IsValue(char c) { /* 合法字符校验 */ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { return true; } return false; } void GList::_Destory(GLNode *p) { /* 销毁广义表 */ if (p == NULL) { return; } //元素结点 if (p->tag == 0) { delete p; this->count--; return; } //子表结点 else { _Destory(p->ptr.hp); _Destory(p->ptr.tp); delete p; this->count--; return; } } int GList::Length() { /* 求广义表长度 */ GLNode *p = this->ls; int length = 0; while (p != NULL) { length++; p = p->ptr.tp; } return length; } int GList::_Depth(GLNode *p) { /* 内部接口:求广义表深度 */ int depth = 0, max_depth = 0; //1.空广义表深度为 1 if (p == NULL) { return 1; } //2.元素结点深度为 0 else if (p->tag == 0) { return 0; } //3.遍历广义表同一层级的子表结点 while (p != NULL) { //求每一个子表深度 depth += 1 + _Depth(p->ptr.hp); //取各子表深度中最大值 if (depth > max_depth) max_depth = depth; //移向下一个子表结点,并初始化深度 depth p = p->ptr.tp; depth = 0; } return max_depth; } int GList::Depth() { /* 公共接口:求广义表深度 */ return _Depth(this->ls); } GLNode *GList::_Copy(GLNode *p) { /* 内部接口:复制广义表 */ //空表 if (p == NULL) { return NULL; } //初始化空结点 GLNode *q = new GLNode(); q->tag = p->tag; //1.元素结点 if (p->tag == 0) { q->data = p->data; } //2.子表结点 else { q->ptr.hp = _Copy(p->ptr.hp); q->ptr.tp = _Copy(p->ptr.tp); } return q; } GList *GList::Copy() { /* 公共接口:复制广义表 */ GList *GList_Copy = new GList(); GList_Copy->ls = _Copy(this->ls); //赋值广义表 GList_Copy->count = _NodeCount(GList_Copy->ls); //统计结点总数(子表结点、元素结点) GList_Copy->s = new string(_ToString(GList_Copy->ls)); //转换成广义表字符串 return GList_Copy; } int GList::_NodeCount(GLNode *p) { /* 内部接口:结点数统计(子表结点、元素结点) */ int cnt = 0; //1.空表 if (p == NULL) { return 0; } //2.元素结点 else if (p->tag == 0) { return 1; } //3.子表结点 else { cnt += 1; cnt += _NodeCount(p->ptr.hp); cnt += _NodeCount(p->ptr.tp); } return cnt; } GList *GList::GetHead() { /* 获取广义表表头 例如: (): 表头:NULL ---- NULL (a): 表头:a (a,b): 表头:a (a,(b,c),d): 表头:a ---- 一个元素结点 ((a,b),c): 表头: (a,b) ---- 一个广义表 注:表头不一定返回的是一个广义表 1.可能是 NULL 2.可能是一个元素结点 3.可能是一个广义表 说明:这里返回的数据类型不能同时做成 GLNode 和 GList 或者说,单元素 a 可以看成 (a) */ GLNode *p = this->ls, *q; //空表时,表头返回 NULL if (p == NULL) { cout << "广义表表头为空!" << endl; return NULL; } //0.创建广义表对象 GList *Head = new GList(); //1.先保存表头结点 tp 指针 q = p->ptr.tp; //2.置空表头结点 tp 指针 p->ptr.tp = NULL; //3.复制表头到 新广义表表头 Head->ls = _Copy(p); //4.恢复表头结点 tp 指针 指向原结点 p->ptr.tp = q; //5.初始化新广义表参数 Head->s = new string(_ToString(Head->ls)); Head->count = _NodeCount(Head->ls); return Head; } GList *GList::GetTail() { /* 获取广义表表尾 例如:满足以下规则 (): 表尾:() (a): 表尾:() (a,b): 表尾:(b) (a,(b,c),d): 表尾:((b,c),d) ((a,b),c): 表尾: (c) 注:表尾一定返回的是一个广义表 */ GLNode *p = this->ls; GList *Tail = new GList(); //创建空广义表对象 //1.空表;2.表尾为空 时,返回空表 if (p == NULL || p->ptr.tp == NULL) { return Tail; } //复制表尾到新广义表,并初始化新广义表参数 Tail->ls = _Copy(p->ptr.tp); Tail->s = new string(_ToString(Tail->ls)); Tail->count = _NodeCount(Tail->ls); return Tail; } string GList::ToString() { /* 公共接口:解析广义表为字符串 */ return "(" + _ToString(this->ls) + ")"; } string GList::_ToString(GLNode *p) { /* 内部接口:解析广义表为字符串 */ //初始化子表结点字符串 string GListString = ""; //a.表头解析 //0.空表 if (p == NULL) { return ""; } //1.元素结点 else if (p->tag == 0) { GListString = p->data; } //2.单元素子表结点 else if (p->ptr.hp->tag == 0) { GListString += _ToString(p->ptr.hp); } //3.多元素子表结点 else if (p->ptr.hp->tag == 1) { GListString += "(" + _ToString(p->ptr.hp) + ")"; } //','分隔符:非最后一个子表结点 if (p->ptr.tp != NULL) GListString += ","; //b.表尾解析 GListString += _ToString(p->ptr.tp); return GListString; }