广义表的实现

描述:

         广义表是一种非线性的数据结构。但如果广义表的每个元素都是原子,它就变成了线性表。广义表广泛地用于人工智能等领域的LISP语言。

        广义表一般记作 LS = (a1, a2, ···, an), n是它的长度,ai可以是单个元素(原子),也可以是广义表(子表),当广义表非空时,称第一个元素a1为LS的表头,称其余元素组成的表为LS的表尾。注意:表头是元素(可以是原子,也可以是广表),表尾一定是广义表。E=(a, E)是一个递归的表。D=(( ),(e),(a,(b,c,d)))是多层次的广义表,长度为3,深度为3。例:((a),a)的表头是(a),表尾是(a),((a))的表头是(a),表尾是( )。


下面给出具体的代码,具体包括了:广义表的定义、创建、求深度、遍历输出、销毁等操作……

 需要说明的是,这里广义表结点存储结构选择的是扩展的线性链接存储。


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<string.h>

typedef enum{ATOM,LIST}ElemTag;  //枚举类型,进行区分表结点与原子结点
typedef struct GLNode            //广义表的基本数据结构
{
	ElemTag tag;                 //标识,区分原子结点与表结点
	union //联合,若是原子,就使用atom标记原子的字符;若是表,则来用记录该表的表头
	{
		char atom;
		GLNode* hp;
	}ptr;
	GLNode* tp;  //指向该表表尾的指针
}*GList;

void InitGList(GList &L)       //初始化一个空的广义表
{
	L=NULL;
}

void CutHead(char* S,char* Hs) 
{            //提取表头表尾的函数:把表S的表头存在Hs中,表尾仍存在S中
	int i=0,j=0;
	int lS=strlen(S);
	while(i<lS&&(S[i]!=','||j!=0))
	{
		if(S[i]=='(')
		{
			j++;
		}
		else if(S[i]==')')
		{
			j--;
		}
		i++;
	}
	if(i<lS)
	{
		int k;
		for(k=0;k<i;k++)
		{
			Hs[k]=S[k];
		}
		Hs[k]=0;
		for(k=i+1;k<lS;k++)
		{
			S[k-i-1]=S[k];
		}
		S[k-i-1]=0;
	}
	else
	{
		int k;
		for(k=0;k<lS;k++)
		{
			Hs[k]=S[k];
		}
		Hs[k]=0;
		S[0]=0;
	}
}

void CreateGList(GList &L,char* S)//根据表字符串S创建广义表
{
	if(strlen(S)==0)          //S为空的情况,即不存在的表
	{
		L=NULL;
	}
	else if(strlen(S)==1)   //该表只有一个元素
	{
		L=(GLNode*)malloc(sizeof(GLNode));
		L->tag=ATOM;
		L->ptr.atom=S[0];
		L->tp=NULL;
	}
	else  //确实是非原子表
	{
		char *Sub=(char*)malloc(sizeof(char)*strlen(S));
		char *hSub=(char*)malloc(sizeof(char)*strlen(S));
		int ls=strlen(S);
		memset(Sub,0,sizeof(char)*ls);
		memset(hSub,0,sizeof(char)*ls);
		int i=0;
		for(i=0;i<ls-2;i++)
			Sub[i]=S[i+1];
		Sub[i]=0;
		
		GLNode *p,*q;
		L=(GLNode*)malloc(sizeof(GLNode));
		p=L;
		p->tag=LIST;
		//q=p;
		
		do
		{
			q=p;
			CutHead(Sub,hSub);  //提取表头表尾
			
			CreateGList(p->ptr.hp,hSub); //递归调用,建立表头的子表
			if(strlen(Sub)>0)
			{
				p=(GLNode*)malloc(sizeof(GLNode));
				p->tag=LIST;
				q->tp=p;
			}
		}while(strlen(Sub)>0);  //循环操作,建立表尾
		q->tp=NULL;
		free(Sub);
		free(hSub);
	}
}

int GListDepth(GList &L)  //求原子表深度的函数
{
	if(L==NULL) return 0;
	if(L->tag==ATOM) return 0;
	int max=0;
	GLNode *p=L;
	while(p!=NULL)
	{
		int depth=GListDepth(p->ptr.hp);
		if(max<depth)
			max=depth;
		p=p->tp;
	}
	return max+1;
}

void GListScan(GList &L)  //遍历原子表函数,并进行了输出操作
{
	if(L==NULL) return;
	if(L->tag==ATOM)
	{
		printf("%c",L->ptr.atom);
		return;
	}
	GLNode *p,*q;
	p=L;
	printf("(");
	while(p!=NULL)
	{
		
		q=p;
		GListScan(p->ptr.hp);
		p=p->tp;
		if(p!=NULL)
			printf(",");
	}
	printf(")");
}

void GListDestroy(GList &L) //对建立的原子表进行销毁,过程与遍历相仿
{
	if(L==NULL) return;
	if(L->tag==ATOM)
	{
		free(L);
		return;
	}
	GLNode *p,*q;
	p=L;
	while(p!=NULL)
	{
		q=p;
		GListDestroy(p->ptr.hp);
		p=p->tp;
		free(q);
	}
}

int main()  //主函数
{
	GList H=NULL;
	
	char s[]="((),(e),(a,(b,c,d)))";//原子表的字符串表示
	CreateGList(H,s);     //创建一个原子表
	printf("%d\n",GListDepth(H));  //输出原子表的深度
	GListScan(H);  //原子表的扫描输出
	printf("\n");
	GListDestroy(H); //程序最后,对原子表进行销毁操作
	return 0;
}

参考资料:http://zh.wikipedia.org/wiki/%E5%B9%BF%E4%B9%89%E8%A1%A8

广义是一种常用的数据结构,它可以示多层次的嵌套结构。在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`函数释放广义的内存。 注意:这只是一个简单的实现示例,实际应用中可能需要根据具体需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值