#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_STR_LEN 100
typedef char AtomType;
typedef enum { ATOM, LIST } ElemTag;
// ATOM==0:原子, LIST==1:子表
typedef struct GLNode {
ElemTag tag; // 标志域
union {
AtomType atom; // 原子结点的数据域
struct { struct GLNode *hp, *tp; } ptr;
};
} *GList;
char hstr[MAX_STR_LEN], istr[MAX_STR_LEN];
void SubString(char *substr, char *inputstr, int start, int end)
{ //截取字符串中间内容,本程序中主要用于去头尾括号
for (char *temp = inputstr + start; temp <= inputstr + end; temp++)
{
*substr = *temp;
*substr++;
}
*substr = '\0';
}
void SplitHeadStr(char *&inputstr, char *&headstr)
{
//将非空串inputstr分割成两个部分,headstr为第一个','之前的子串,inputstr为之后的字串
int n = strlen(inputstr);
int i = 0;
int k = 0; //记录尚为配对的左括号的个数
do {
//找出最高层头尾分隔点
//由于字符串最外面没有括号,所以找到逗号的时候左右括号数应该相等,否则不是最高层
if (inputstr[i] == '(')
k++;
else if (inputstr[i] == ')')
k--;
i++;
} while (i < n && (inputstr[i] != ',' || k != 0));
if (i < n) {
SubString(headstr, inputstr, 0, i - 1);
SubString(inputstr, inputstr, i + 1, strlen(inputstr) - 1);
}
else {
strcpy(headstr, inputstr);
inputstr = '\0';
}
}
int CreateGList(GList &L, char *s)
{
if (strcmp(s, "()") == 0)
L = NULL; //建立空表
else {
L = (GList)malloc(sizeof(struct GLNode)); //新建一个表结点
if (L == NULL)
return -1;
if (strlen(s) == 1) { //原子结点
L->tag = ATOM;;
L->atom = *s;
}
else {
char *headstr = hstr;
L->tag = LIST;
SubString(s, s, 1, strlen(s) - 2); //脱去最外边的括号
GList pointer = L;
do { //创建子表
SplitHeadStr(s, headstr); //headstr为分割后的表头,s为分割后的表尾
char tstr[MAX_STR_LEN];
strcpy(tstr, headstr);
CreateGList(pointer->ptr.hp, tstr); //递归创建表头
if (s != NULL && strlen(s) != 0) { //如果表尾不为空的话
GList tailnode = (GList)malloc(sizeof(struct GLNode));
if (pointer == NULL)
return -1;
tailnode->tag = LIST; //广义表的表尾肯定是一张表
pointer->ptr.tp = tailnode;
pointer = tailnode;
}
} while (s != NULL && strlen(s) != 0); //直到表尾为空NULL则退出
pointer->ptr.tp = NULL; //最后将表尾赋值为NULL
}
}
return 0;
}
void PrintGList(const GList L) {
printf("(");
GList pointer = L;
do {
GList temp = pointer->ptr.hp;
if (temp != NULL) { //递归输出表头中原子结点
if (temp->tag == ATOM)
{
printf("%c", temp->atom);
}
else
{
PrintGList(temp);
}
}
if (pointer->ptr.tp != NULL)
{ //后面还有
printf(",");
}
pointer = pointer->ptr.tp; // 指针指向表尾,判断表尾是否空
} while (pointer != NULL);
printf(")");
}
int GetGListDepth(GList L)
{
if (!L)
return 1;//空表
if (L->tag == ATOM)
return 0;//原子
int max = 0;
for (GList pp = L; pp; pp = pp->ptr.tp)
{
int dep = GetGListDepth(pp->ptr.hp);
if (dep > max) {
max = dep;//每次找到表中遍历到深度最大的表,并用max记录
}
}
return max + 1;
}
int main() {
char s[100];
scanf("%s", &s);
int left = 0, right = 0;
for (int i = 0; i < strlen(s); i++)
{
if (s[i] == '(')
left++;
if (s[i] == ')')
right++;
}
if (left != right)
{
printf("error");
return -1;
}
strcpy(istr, s);
GList L;
char *head=(char*)malloc(MAX_STR_LEN*sizeof(char)), *tail=(char*)malloc(MAX_STR_LEN * sizeof(char));
strcpy(tail, istr);
CreateGList(L, istr);
SubString(tail, tail, 1, strlen(tail) - 2);
printf("广义表:");
PrintGList(L);
SplitHeadStr(tail, head);
printf("\nhead:%s\ntail:%s\n",head,tail);
printf("\n深度:%d", GetGListDepth(L));
return 0;
}