产出
优快云 技术博客 1 篇
一、问题引入
实现广义表的基本运算
目的:领会广义表的链式存储结构及其基本算法设计
内容编写一个程序 exp6-2.cpp,实现广义表的各种运算,并在此基础上设计一个主程序,完
成如下功能:
- 建立广义表 g="(b,(b,a,(#),d),((a,b),c,((#))))"的链式存储结构。
- 输出广义表 g 的长度。
- 输出广义表 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
执行结果类似下图:
二、所需函数
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;
}