描述:
广义表是一种非线性的数据结构。但如果广义表的每个元素都是原子,它就变成了线性表。广义表广泛地用于人工智能等领域的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