/**
* 实验题目:
* 实现广义表的基本运算
* 实验目的:
* 领会广义表的链式存储结构及其基本算法设计
* 实验内容:
* 实现广义表的各种运算,设计一个程序,实现如下功能:
* 1、建立广义表g = "(b,(b,a,(#),d),((a,b),c,((#))))"的链式存储结构
* 2、输出广义表g的长度
* 3、输出广义表g的深度
* 4、输出广义表g的最大原子
*/
#include <stdio.h>
#include <malloc.h>
typedef struct lnode
{
int tag; // 结点类型标识
union
{
char data;
struct lnode *sublist;
}val;
struct lnode *link; // 指向下一个元素
}GLNode; // 声明广义表结点类型
/*---------------返回由括号表示法表示s的广义表链式存储结构(递归方法)----------------*/
static GLNode *create_gl(char *&s)
{
GLNode *g;
char ch = *s++; // 取一个字符
if(ch != '\0') // 串未结束判断
{
g = (GLNode *)malloc(sizeof(GLNode)); // 创建一个新结点
if(ch == '(') // 当前字符为左括号时
{
g->tag = 1; // 新结点作为表头结点
g->val.sublist = create_gl(s); // 递归构造子表并链到表头结点
}
else if(ch == ')') // 遇到右括号字符,g设置为空
{
g = NULL;
}
else if(ch == '#') // 遇到#字符,表示空表
{
g->val.sublist = NULL;
}
else // 为原子字符
{
g->tag = 0; // 新结点作为原子结点
g->val.data = ch;
}
}
else // 串结束,g设置为空
{
g = NULL;
}
ch = *s++; // 取下一个字符
if(g != NULL) // 串未结束,继续构造兄弟结点
{
if(ch == ',') // 当前字符为逗号
{
g->link = create_gl(s); // 递归构造兄弟结点
}
else // 没有兄弟了,将兄弟指针设置为NULL
{
g->link = NULL;
}
}
return g; // 返回广义表g
}
/*---------------输出广义表g----------------*/
static void disp_gl(GLNode *g)
{
if(g != NULL) // 表非空判断
{
if(g->tag == 0) // g的元素为原子时
printf("%c", g->val.data); // 输出原子值
else // g的元素为子表时
{
printf("(");
if(g->val.sublist == NULL) // 为空表时
printf("#");
else // 为非空子表时
disp_gl(g->val.sublist); // 递归输出子表
printf(")");
}
if(g->link != NULL)
{
printf(",");
disp_gl(g->link); // 递归输出g的兄弟
}
}
}
/*---------------求广义表g的长度----------------*/
static int gl_length(GLNode *g)
{
int n = 0;
g = g->val.sublist; // g指向广义表的第一个元素
while(g != NULL)
{
n++;/*---------------求广义表g的最大原子----------------*/
g = g->link;
}
return n;
}
/*---------------求广义表g的深度----------------*/
static int gl_depth(GLNode *g)
{
int max_dep = 0;
int dep;
if(g->tag == 0)
return 0;
g = g->val.sublist; // g指向第一个元素
if(g == NULL) // 为空表时返回1
return 1;
while(g != NULL) // 遍历表中的每一个元素
{
if(g->tag == 1) // 元素为子表的情况
{
dep = gl_depth(g); // 递归调用求出子表的深度
if(dep > max_dep)
max_dep = dep; // max_dep为同一层所求过的子表中深度的最大值
}
g = g->link; // g指向下一个元素
}
return (max_dep + 1); // 返回表的深度
}
/*---------------求广义表g的最大原子----------------*/
static char gl_max_atom(GLNode *g)
{
char max1, max2;
if(g != NULL)
{
if(g->tag == 0)
{
max1 = gl_max_atom(g->link);
return (g->val.data > max1 ? g->val.data : max1);
}
else
{
max1 = gl_max_atom(g->val.sublist);
max2 = gl_max_atom(g->link);
return (max1 > max2 ? max1 : max2);
}
}
else
return 0;
}
/*---------------销毁广义表g----------------*/
static void destroy_gl(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临时保存兄弟结点
destroy_gl(g1); // 递归释放g1所指子表的空间
g1 = g2; // g1指向后继兄弟结点
}
}
free(g); // 释放头结点空间
}
int main(void)
{
GLNode *g;
char *str = "(b,(b,a,(#),d),((a,b),c,((#))))";
g = create_gl(str);
printf("广义表g:");
disp_gl(g);
printf("\n");
printf("广义表g的长度:%d\n", gl_length(g));
printf("广义表g的深度:%d\n", gl_depth(g));
printf("广义表g的最大原子:%c\n", gl_max_atom(g));
destroy_gl(g);
return 0;
}
测试结果:
广义表g:(b,(b,a,((#)),d),((a,b),c,(((#)))))
广义表g的长度:3
广义表g的深度:4
广义表g的最大原子:d