广义表的创建与深度
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
//算法:
//测str长度,三种情况,最后一种创建List L,p;
//删除str括号,(先创建,再删除)
//判断str长度(未删除括号)
//获取hstr,与subs.
//递归构造
//回溯head连接子女L,q;
//测subs长度
//1.taul连结兄弟,(只是创建)
//2.再次获取hstr与subs
//3.递归构造
//4.回溯head连结子女
//5.测subs长度
//......
//p->tail=NULL;
//无论见到什么都要创建1 空 空
/*大体过程:(先列出所有划分)
1.创建(三种情况,其他两种直接回溯)
2.去括号
3.取头尾
4.创建(头,三种情况,其他两种直接回溯)
5.回溯连子女
6.有尾创建连兄弟,无尾回溯连子女
7.取头尾*/
/*眼看深度:
空表,空,单字符不计数,前面几个左括号就是深度*/
typedef enum
{
ATOM,LIST//注意这没分号
}ElemTag;
typedef struct GLnode
{
ElemTag tag;
union
{
char atom; //char 表示原子型,struct 表示表
struct
{
struct GLnode *head,*tail;
}htp;
}atom_htp;
}GLNode,*GList;
int Depth(GLNode* L)
{
int d;
int maxn=0;
GLNode *s;
if(L==NULL)
return 1; //空表的深度为1;
if(L->tag==ATOM)
return 0; //原子表的深度为0;
s=L;
while(s!=NULL) //同一层的每个都到头
{
d=Depth(s->atom_htp.htp.head);
if(d>maxn)
maxn=d;
s=s->atom_htp.htp.tail;
}
return (maxn+1);
}
void getsubs(char str[],char hstr[]) //删除括号的的情况:1.左括号,2.数字
{
int i=0,j=0,k=0,r=0;
char s[100000];
while(str[i]&&(str[i]!=','||k)) //到字符数组最尾或(str[i]==','且括号左右括号抵消)跳出循环
{ //如(),或直接,这两种情况。
if(str[i]=='(') // 12 3 str[3]跳出循环
k++;
else if(str[i]==')')
k--;
if(str[i]!=','||(str[i]==','&&k))//不等于','就只有'(',')','a'这三种情况
{ //str[i]==','&&k就是说这个','是在括号内的合法的',';
hstr[j]=str[i];
i++;
j++;
}
}
hstr[j]='\0'; //所以hstr[]存的是当前的头,注意,由上面的if可知,hstr[]不带逗号。
if(str[i]==',') //因为可能是到终点才结束的,所以这if才有意义
i++;
while(str[i])
{
s[r]=str[i]; //s[r]存的是当前的尾。
r++;
i++;
}
s[r]='\0';
strcpy(str,s);//subs变成当前尾。
return;
}
GList CreateGList(char str[]) //还是为了->个符号的操作。//L是第二层了。
{
GLNode *L;
char subs[100000]; //是只有子女,没有兄弟的广义表
char hstr[100000];
GLNode* q; //头是指子女,尾是指兄弟
int len=strlen(str);
if(len==0||strcmp(str,"()")==0) //空表的两种情况,不创建空间
L=NULL;
else if(len==1) //原子结点的情况。
{
if(!(L=(GLNode *)malloc(sizeof(GLNode)))) //广义表外面必须要有括号,没括号就一种原子结点的情况。
exit(0); //L不是总体,而是第一个兄弟
L->tag=ATOM; //第一个兄弟是相对同层括号而言的
L->atom_htp.atom=str[0];
L->atom_htp.htp.tail=NULL;//感觉有必要添加
}
else
{
GLNode *p; //p是用来 创建空间的,q是用来纪录当前创建位置的,创建空间的时候,紧接着就是去括号
if(!(L=(GLNode *)malloc(sizeof(GLNode))))
exit(0);
L->tag=LIST;//定L为表结点
p=L; //储存头结点的地址
str++; //str的地址变成str[1]的地址,也就删掉了第一个左括号
strncpy(subs,str,len-2); //删右括号,
subs[len-2]='\0';
while(len>0) //初始的len是最开始str的len
{
GLNode* r;
getsubs(subs,hstr); //得到的hstr恰好是一个头。(表或原子)
r=CreateGList(hstr);//因为是递归构建,所以函数应该返回地址,然都公用一个地址就弄乱了,并且再次以头创建链表
p->atom_htp.htp.head=r;//创建递归回来之后才将下连接到上。
q=p;
len=strlen(subs);//第二次测len是裁剪之后,因为调用了getsubs(subs,hstr)后,subs被剪裁了
if(len>0) //如果不为空,则继续创建同层次的表。如果为空,同层次接NULL,并跳出循环。
{
if(!(p=(GLNode*)malloc(sizeof(GLNode))))
exit(0);
p->tag=LIST;
q->atom_htp.htp.tail=p;
}
}
p->atom_htp.htp.tail=NULL;
}
return L;
}
int main()
{
GLNode* L;
char str[100000];
scanf("%s",str);
L=CreateGList(str);
printf("%d\n",Depth(L));
printf("%d\n",Depth(L));
return 0;
}