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


产出

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;
}

四、 运行结果

在这里插入图片描述

  • 9
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
广义表是一种常用的数据结构,它可以表示多层次的嵌套结构。在C语言中,可以使用链表来实现广义表。 以下是一个简单的广义表C语言代码实现: ```c #include <stdio.h> #include <stdlib.h> // 结点的数据类型定义 typedef struct Node { char data; // 数据域,存储广义表的元素 struct Node* next; // 指针域,指向下一个结点 struct Node* sublist; // 子表指针,指向子表的头结点 } Node; // 创建结点 Node* createNode(char data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; newNode->sublist = NULL; return newNode; } // 插入结点到广义表中 void insert(Node** head, char data) { if (*head == NULL) { *head = createNode(data); return; } Node* current = *head; while (current->next != NULL) { current = current->next; } current->next = createNode(data); } // 插入子表到广义表中 void insertSublist(Node** head, Node* sublist) { if (*head == NULL) { *head = sublist; return; } Node* current = *head; while (current->next != NULL) { current = current->next; } current->next = sublist; } // 打印广义表 void printList(Node* head) { if (head == NULL) { printf("()"); return; } printf("("); Node* current = head; while (current != NULL) { if (current->sublist == NULL) { printf("%c", current->data); } else { printList(current->sublist); } if (current->next != NULL) { printf(", "); } current = current->next; } printf(")"); } // 释放广义表的内存 void freeList(Node** head) { Node* current = *head; while (current != NULL) { Node* temp = current; current = current->next; if (temp->sublist != NULL) { freeList(&temp->sublist); } free(temp); } *head = NULL; } int main() { Node* list = NULL; // 插入元素到广义表中 insert(&list, 'A'); insert(&list, 'B'); insert(&list, 'C'); // 创建子表并插入到广义表中 Node* sublist = createNode('D'); insert(&sublist->sublist, 'E'); insert(&sublist->sublist, 'F'); insertSublist(&list, sublist); // 打印广义表 printList(list); // 释放广义表的内存 freeList(&list); return 0; } ``` 这段代码实现了一个简单的广义表,可以通过调用`insert`和`insertSublist`函数插入元素和子表,并通过`printList`函数打印整个广义表。记得在程序结束时,调用`freeList`函数释放广义表的内存。 注意:这只是一个简单的实现示例,实际应用中可能需要根据具体需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值