数据结构之广义表(头尾链表表示法)(递归版)(C++)

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

猜你喜欢

转载自blog.csdn.net/weixin_39469127/article/details/80384965