【数据结构】实现广义表的基本运算


产出

CSDN 技术博客 1 篇

一、问题引入

实现广义表的基本运算
目的:领会广义表的链式存储结构及其基本算法设计
内容编写一个程序 exp6-2.cpp,实现广义表的各种运算,并在此基础上设计一个主程序,完
成如下功能:

  1. 建立广义表 g="(b,(b,a,(#),d),((a,b),c,((#))))"的链式存储结构。
  2. 输出广义表 g 的长度。
  3. 输出广义表 g 的深度。
  4. 输出广义表 g 的最大原子。
    提示:功能算法如下
    ➢ CreateGL(char *&s) //返回由括号表示法表示 s 的广义表链式存储结构
    ➢ GLLength(GLNode *g) //求广义表 g 的长度
    ➢ GLDepth(GLNode *g) //求广义表 g 的深度
    ➢ DispGL(GLNode *g) //输出广义表 g
    ➢ maxatom(GLNode *g) //求广义表 g 中最大原子
    ➢ DestroyGL(GLNode *&g) //销毁广义表 g
    执行结果类似下图:
    在这里插入图片描述

二、所需函数

CreateGL(char *&s) //返回由括号表示法表示 s 的广义表链式存储结构
➢ GLLength(GLNode *g) //求广义表 g 的长度
➢ GLDepth(GLNode *g) //求广义表 g 的深度
➢ DispGL(GLNode *g) //输出广义表 g
➢ maxatom(GLNode *g) //求广义表 g 中最大原子
➢ DestroyGL(GLNode *&g) //销毁广义表 g

三、代码实现

代码如下(示例):

#include <stdio.h>
#include <malloc.h>

typedef char elem;

typedef struct Inode
{
	int tag;					//用于识别单元素与子表
	union						//大括号中多选一
	{
		elem data;				//单元素
		struct Inode *sublist;	//子表
	}val;
	struct Inode *link;			//指向下一个元素
}GLNode;


//创建广义表
GLNode *CreateGL(elem *&s)
{
	GLNode *g;									//创建广义表指针
	elem c = *s++;
	if(c != '\0')								//字符串未遍历完
	{
		g = (GLNode*)malloc(sizeof(GLNode));	//创建广义表结点
		if(c == '(')							//如果是'('则为子表
		{
			g -> tag = 1;						//tag为1,表示是子表
			g -> val.sublist = CreateGL(s);		//递归填充子表
		}
		else if(c == ')')						//如果')'子表结束
		{
			g = NULL;							//将g置空
		}
		else if(c == '#')						//如果为#则,将子表置空
			g -> val.sublist = NULL;
		else
		{										//最后一种情况,不是子表,而是原子
			g -> tag = 0;						//tag为0,表示是单个原子
			g -> val.data = c;					//数据域赋值
		}
	}
	else										//字符串遍历完,g指针置空
		g = NULL;
	c = *s++;									//获取字符串当前字符
	if(g != NULL)								//若g未被置空,证明字符串未被遍历完
	{
		if(c == ',')							//若是“,”表示后面仍有兄弟,继续创建广义表
			g -> link = CreateGL(s);
		else									//否则将g置空
			g -> link = NULL;
	}
	return g;									//最终返回g指针
}

//求广义表长度
int GLlength(GLNode *g)
{
	int n = 0;									//用于计元素个数
	g = g -> val.sublist;						//找到子表
	while(g != NULL)							//如果g不为空
	{
		n++;									
		g = g -> link;							//找到下一个兄弟
	}
	return n;									//返回n
}

//输出广义表
void DispGL(GLNode *g)
{
	if(g != NULL)								//如果g不为空
	{
		if(g -> tag == 0)						//如果元素是原子
			printf("%c", g -> val.data);		//打印数值
		else
		{
			printf("(");						//是子表打印'('
			if(g -> val.sublist == NULL)		//如果是空表,则打印'#'
				printf("#");
			else								//否则递归输出广义表
			{
				DispGL(g -> val.sublist);
			}
			printf(")");
		}
		if(g -> link != NULL)					//广义表是否为遍历完毕
		{
			printf(",");						//打印','
			DispGL(g -> link);					//递归输出广义表
		}
	}
}


//求广义表深度
int GLDepth(GLNode *g)
{
	int max = 0, dep;							//max记录最大深度,dep记录当前子表最大深度
	if(g -> tag == 0)							//如果是原子,深度为0
		return 0;
	g = g -> val.sublist;						//访问广义表
	if(g == NULL)								//如果是空表,则深度为1
		return 1;
	while(g != NULL)							//广义表未遍历完全
	{
		if(g -> tag == 1)						//若是子表,则递归GLDepth,将最大子表深度赋值给max
		{
			dep = GLDepth(g);
			if(dep > max)
				max = dep;
		}
		g = g -> link;							//指向后继兄弟结点
	}
	return(max + 1);
}

//求最大原子
elem maxatom(GLNode *g)
{
	elem max1, max2;
	if(g != NULL)
	{
		if(g -> tag == 0)										//如果是原子
		{
			max1 = maxatom(g -> link);							//与下一个兄弟比较
			return(g -> val.data > max1?g -> val.data:max1);
		}
		else
		{
			max1 = maxatom(g -> val.sublist);					//当前子表最大原子
			max2 = maxatom(g -> link);							//求下一个兄弟最大原子
			return(max1 > max2?max1:max2);						//两者比较大小
		}
	}
}

//销毁广义表 g
void DestroyGL(GLNode *&g)
{ 
	GLNode *g1,*g2;
	g1=g->val.sublist; 				//g1 指向广义表的第一个元素
	while (g1!=NULL) 				//遍历所有元素
	{ 
		if (g1->tag==0) 			//若为原子节点
		{
			g2=g1->link; 			//g2 临时保存兄弟节点
			free(g1); 				//释放 g1 所指原子节点
			g1=g2; 					//g1 指向后继兄弟节点
		}
		else 						//若为子表
		{ 
			g2=g1->link; 			//g2 临时保存兄弟节点
			DestroyGL(g1); 			//递归释放 g1 所指子表的空间
			g1=g2; 					//g1 指向后继兄弟节点
		}
	}
	free(g); 						//释放头节点空间
}


int main()
{
	elem *str = "(b,(b,a,(#),d),((a,b),c,((#))))";	//创建字符串
	GLNode *g = CreateGL(str);						//创建广义表
	printf("广义表g:");
	DispGL(g);										//输出广义表
	printf("\n");
	printf("广义表g的长度:%d\n", GLlength(g));		//求广义表长度
	printf("广义表g的深度:%d\n", GLDepth(g));		//求广义表深度
	printf("最大原子:%c\n", maxatom(g));			//求最大原子
	DestroyGL(g);									//销毁广义表
	return 0;
}

四、 运行结果

在这里插入图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页