广义表理论上很好理解,但是我感觉对我来说上手还有点困难(还是太菜)。
先看广义表的一些定义吧
1 )什么是广义表
广义表,又称列表,也是一种线性存储结构,既可以存储不可再分的元素,也可以存储广义表,记作:LS = (a1,a2,…,an),其中,LS 代表广义表的名称,an 表示广义表存储的数据,广义表中每个 ai 既可以代表单个元素,也可以代表另一个广义表。
2 )广义表的原子和子表
广义表中存储的单个元素称为 “原子”,而存储的广义表称为 “子表”。
例如 :广义表 LS = {1,{1,2,3}},则此广义表的构成 :广义表 LS 存储了一个原子 1 和子表 {1,2,3}。
广义表存储数据的一些常用形式:
A = ():A 表示一个广义表,只不过表是空的。
B = (e):广义表 B 中只有一个原子 e。
C = (a,(b,c,d)) :广义表 C 中有两个元素,原子 a 和子表 (b,c,d)。
D = (A,B,C):广义表 D 中存有 3 个子表,分别是A、B和C。这种表示方式等同于 D = ((),(e),(b,c,d)) 。
E = (a,E):广义表 E 中有两个元素,原子 a 和它本身。这是一个递归广义表,等同于:E = (a,(a,(a,…)))。
3 ) 广义表的表头和表尾
当广义表不是空表时,称第一个数据(原子或子表)为"表头",剩下的数据构成的新广义表为"表尾"。
除非广义表为空表,否则广义表一定具有表头和表尾,且广义表的表尾一定是一个广义表。
具体定义详见原文链接:https://blog.youkuaiyun.com/weixin_44289254/article/details/123693094
再看题上,其实本人感觉难的点其实是输入与创建广义表
我也是看着大佬的照猫画虎来的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {ATOM,LIST}ElemTag;//ATOM为0,LIST为1
//广义表的头尾链表存储结构
typedef struct GLnode
{
ElemTag tag;//标志
union
{
char atom;//原子节点
struct
{
struct GLnode *head;//表节点
struct GLnode *tail;
}ptr;//头节点,尾节点
}un;
}GLnode,*GList;
//广义表的同层节点链存储结构
typedef struct GGlnode
{
ElemTag tag;
union
{
char atom;
struct GGlnode *head;
}un;
struct GGlnode *tail;
}GGlnode,*GGlist;
//创建原子节点
void CreateAtom(GList c,char ch)
{
c->tag=ATOM;
c->un.atom=ch;
}
//创建子表节点
void CreateList(GList c)
{
c->tag=LIST;
c->un.ptr.head=NULL;
c->un.ptr.tail=NULL;
}
//定位函数,让广义表回到输入应该属于的层数上来
char* Location(char *str)
{
if(str[0]=='\0') return 0;//无字符情况
int flag=1,len=strlen(str);//flag标志()的情况
int i;
for(i = 0; i < len; i++) {
if (str[i] == '(') {
flag++;
}
if (str[i] == ')') {
flag--;
}
if (flag == 0) {
break;
}
}
if (str[i+1] == '\0') {
return 0;
}
return (str+i+1);//指向下一个字符
}
//创建广义表
void CreateGlist(GList s,char *str)
{
if(str[0] == '(')//下一个为字母
{
CreateList(s);//子表
s->un.ptr.head=(GList)malloc(sizeof(GLnode));//开辟空间
str=str+1;//从(移动
CreateGlist(s->un.ptr.head,str);//递归写入
str=Location(str);//下一个
if(str==0)
{
return;
}
}
else if( str[0]==')')
{
return;//用于递归
}
else if(str[0]==',')//下一个为字母
{
s->un.ptr.tail=(GList)malloc(sizeof(GLnode));//开辟空间
str = str + 1;
CreateGlist(s->un.ptr.tail,str);//递归写入
return;
}
else//此时为字母
{
CreateList(s);//子表
s->un.ptr.head=(GList)malloc(sizeof(GLnode));
CreateAtom(s->un.ptr.head,str[0]);//原子节点
str=str+1;
}
//下一个字符
if(str[0] == ')') return;
else if(str[0]==',')
{
s->un.ptr.tail=(GList)malloc(sizeof(GLnode));
str=str+1;
CreateGlist(s->un.ptr.tail,str);
return;
}
}
//同层节点链存储结构创建广义表
void CCreateGlist(GGlist s,char *str)
{
if(str[0]=='(')
{
s->tag=LIST;
s->un.head=(GGlist)malloc(sizeof(GGlnode));
str=str+1;
CCreateGlist(s->un.head,str);
str=Location(str);
if (str == 0) {
return;
}
}
else if(str[0]==')')
{
s=NULL;
return;
}
else if(str[0]==',')
{
s->tail=(GGlist)malloc(sizeof(GGlnode));
str=str+1;
CCreateGlist(s->tail,str);
return;
}
else//字母
{
s->tag=ATOM;
s->un.atom=str[0];
str=str+1;
}
if(str[0]==')')
{
s->tail=NULL;
return;
}
else if(str[0]==',')
{
s->tail=(GGlist)malloc(sizeof(GGlnode));
str=str+1;
CCreateGlist(s->tail,str);
return;
}
}
//求广义表深度
int Depth(GList s)
{
int temp=0,max=0;
GList p;
p=s;
if(s==NULL) return 1;//空表深度为
if(s->tag==ATOM) return 0;//原子节点深度为0
while(p!=NULL)
{
temp=Depth(p->un.ptr.head);
if(temp>max)
{
max=temp;
}
p=p->un.ptr.tail;
}
return(max+1);//表的深度等于最深子表加一
}
//同层节点链存储结构创建广义表
//求深度
int DDepth(GGlist s)
{
int temp=0,max=0;
GGlist p;
p=s->un.head;
if(s->tag==ATOM) return 0;
if(p==NULL) return 1;
while(p!=NULL)
{
if(p->tag==LIST)
{
temp=DDepth(p);
}
if(temp>max)
{
max=temp;
}
p=p->tail;
}
return (max+1);
}
int main()
{
int dep,ddep;
char *str;
str=(char *) malloc (sizeof(char));
GLnode a;
GGlnode b;
scanf("%s",str);
CreateGlist(&a,str+1);
CCreateGlist(&b,str);
dep=Depth(&a);
ddep=DDepth(&b);
printf("%d\n%d",dep,ddep);
return 0;
}
大神连接:https://blog.youkuaiyun.com/weixin_53068269/article/details/115681434