//文件名:"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;
}