NOJ-求广义表的深度(C语言描述)
NOJ-求广义表的深度
第一次写博客,希望能够记录下自己的心得体会,如有错误, 欢迎指正。
广义表的基本概念
- 广义表是线性表的推广,是典型的递归定义。
- 广义表由两部分组成——表头(Head),表尾(tail)。第一个元素称为表头,其余元素称为表尾。
- 广义表的特点:
1. 列表的元素可以是子表,而子表的元素还可以是子表。
2. 列表可为其他列表共享。
3. 列表可以是一个递归的表,即列表也可以是本身的一个子表。
广义表的存储结构
typedef enum{ATOM,LIST} ElemTag;//ATOM代表原子,LIST代表子表
typedef struct GLNode{ElemTag tag;//公共部分,用于区分原子结点和表结点union{char atom;//原子结点的值struct {struct GLNode *hp, *tp;} ptr;//ptr是表结点的指针域,*hp指向表头,*tp指向表尾};
} * GList,GLNode;
结点的结构:
- 标志域 tag用于区分原子结点和表结点。
- 指针域 union部分。 如果是表结点则是指向表头和表尾的指针,如果是原子结点则是值域,代表该原子结点的值。
广义表的建立
void SubString(char sub[], char S[], int start, int len);//脱外层括号
void sever(char str[], char hstr[]);//将str,之前的部分给hstr,在str中删掉hstr和,
void CreateGList(GList *L, char *S);//创建广义表
主要函数如上
脱外层括号
void SubString(char sub[], char S[], int start, int len)
{int i = 0;for (i=0;i<len;i++)sub[i] = S[i + start - 1];sub[i] = '\0';
}
这一部分用于将一个字符数组的一部分复制到另一个字符数组中,这样做是为了分离出表头和表尾。在下一个函数中有解释。
分离表头和表尾
void sever(char *str,char *hstr)
{int i,k;//k记录左括号数for (i=0,k=0;i<strlen(str);i++){if(str[i]=='(')k++;if(str[i]==')')k--;if(k==0&&str[i]==',')break;}//此时的i为表头和表尾的分界if(i<strlen(str)){SubString(hstr, str, 1, i);//表头字符串SubString(str, str, i + 2, strlen(str) - i - 1);//表尾字符串}//表尾不空else{SubString(hstr, str, 1, strlen(str));str[0] = 0;}//表尾空
}
在这一部分中,传入一个去掉左右括号的字符串。
表头和表尾的分界点是:
从左到右遍历这个字符串如果遇到的左括号等于遇到的右括号且i所指的字符是‘,’那么就说明到了表头表尾的分界点
- 如果遍历完了,说明表尾是空表,把这个字符数组直接赋给表头,所以表尾的字符数组直接给第一个元素赋予0。
- 但是如果没有遍历完,说明表尾不空,那么把逗号之前赋给表头,逗号之后赋给表尾。
创建广义表
我觉得这部分是最难的,比求广义表的深度更难,因为它也是一个递归建立。
void CreateGList(GList *L, char *S)
{GList p=(GList)malloc(sizeof(GLNode));GList q=(GList)malloc(sizeof(GLNode));char hsub[100]={0};if(S==NULL)(*L) = NULL; //如果传入空字符,就创建空表else{(*L) = (GList)malloc(sizeof(GLNode));if(strlen(S)==1){(*L)->tag = ATOM;(*L)->atom = *S;}else{SubString(S, S, 2, strlen(S) - 2);//脱去外层括号p = (*L);p->tag = LIST;do{//重复建n个子表sever(S, hsub);//从sub中分离出表头串hsubCreateGList(&(p->ptr.hp), hsub);if((*S)!=0){q = p;p = (GList)malloc(sizeof(GLNode));p->tag = LIST;q->ptr.tp = p;}} while ((*S) != 0);p->ptr.tp = NULL;}}
}
分三种情况
- 传入一个空指针,则建立空表。
- 若传入一个字符,则建立一个只有原子的结点的广义表。
- 否则,则进行如下操作:
脱去外层括号;
从S中分离出表头hsub然后递归调用CreateGList函数;
若表尾结点非空,则把表尾结点插入在表尾。
广义表深度的递归法
int GListDepth(GList L)
{if(!L)return 1;if(L->tag==ATOM)return 0;int max = 0,dep;GList p;for (p = L; p; p = p->ptr.tp){dep = GListDepth(p->ptr.hp);if(dep>max)max = dep;}return (max + 1);
}
递归定义为:
- 当L为空表时,深度为1;
- 当L为原子时,深度为0;
- 归纳:Depth=1+MAX{Depth(α)}
所以这部分递归是比较简单的,只用不断在指针非空的情况下遍历广义表,遇到更大的就更新MAX的值。
完整代码为:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef enum{ATOM,LIST} ElemTag;//ATOM代表原子,LIST代表子表
typedef struct GLNode{ElemTag tag;//公共部分,用于区分原子结点和表结点union{char atom;//原子结点的值struct {struct GLNode *hp, *tp;} ptr;//ptr是表结点的指针域,*hp指向表头,*tp指向表尾};
} * GList,GLNode;
void SubString(char sub[], char S[], int start, int len);//脱外层括号
void sever(char str[], char hstr[]);//将str,之前的部分给hstr,在str中删掉hstr和,
void CreateGList(GList *L, char *S);//创建广义表
int GListDepth(GList L);//广义表深度递归求法int main()
{char S[100] = {0};scanf("%s", S);GList L = (GList)malloc(sizeof(GLNode));CreateGList(&L, S);int n = GListDepth(L);printf("%d\n%d", n,n);
}
void SubString(char sub[], char S[], int start, int len)
{int i = 0;for (i=0;i<len;i++)sub[i] = S[i + start - 1];sub[i] = '\0';
}
void sever(char *str,char *hstr)
{int i,k;//k记录左括号数for (i=0,k=0;i<strlen(str);i++){if(str[i]=='(')k++;if(str[i]==')')k--;if(k==0&&str[i]==',')break;}//此时的i为表头和表尾的分界if(i<strlen(str)){SubString(hstr, str, 1, i);//表头字符串SubString(str, str, i + 2, strlen(str) - i - 1);//表尾字符串}//表尾不空else{SubString(hstr, str, 1, strlen(str));str[0] = 0;}//表尾空
}
void CreateGList(GList *L, char *S)
{GList p=(GList)malloc(sizeof(GLNode));GList q=(GList)malloc(sizeof(GLNode));char hsub[100]={0};if(S==NULL)(*L) = NULL; //如果传入空字符,就创建空表else{(*L) = (GList)malloc(sizeof(GLNode));if(strlen(S)==1){(*L)->tag = ATOM;(*L)->atom = *S;}else{SubString(S, S, 2, strlen(S) - 2);//脱去外层括号p = (*L);p->tag = LIST;do{//重复建n个子表sever(S, hsub);//从sub中分离出表头串hsubCreateGList(&(p->ptr.hp), hsub);if((*S)!=0){q = p;p = (GList)malloc(sizeof(GLNode));p->tag = LIST;q->ptr.tp = p;}} while ((*S) != 0);p->ptr.tp = NULL;}}
}int GListDepth(GList L)
{if(!L)return 1;if(L->tag==ATOM)return 0;int max = 0,dep;GList p;for (p = L; p; p = p->ptr.tp){dep = GListDepth(p->ptr.hp);if(dep>max)max = dep;}return (max + 1);
}
NOJ-求广义表的深度(C语言描述)相关推荐
- 求广义表的深度代码解读
广义表的头节点必定是1. int ListsDepth (Lslink LS) //广义表采用单链结构 { int max=0; //默认情况下,认为表if (LS->atom==0) retu ...
- 广义表-求广义表深度,建立广义表,复制广义表
广义表-求广义表深度,建立广义表,复制广义表 例: 广义表(a,(a,b),d,e,((i,j),k)) 求广义表的长度和深度 长度为5,深度为3 长度:有效逗号个数+1 深度:有效括号个数 求广义表 ...
- 数据结构14——求广义表深度(严5.30)
Description 试按表头.表尾的分析方法编写求广义表的深度的递归程序. Input 输入一串以'('开始,以'('结束的字符串,并且输入的左右括号必须匹配,如:(),(())-- Output ...
- 求广义表深度(严5.30)
Description 试按表头.表尾的分析方法编写求广义表的深度的递归程序. Input 输入一串以'('开始,以'('结束的字符串,并且输入的左右括号必须匹配,如:(),(())-- Output ...
- 西北工业大学NOJ数据结构—014求广义表深度
#include <stdio.h> #include <stdlib.h>typedef struct Node {int A_L;//使用枚举不熟练,A_T代表Atom或L ...
- 广义表的深度和长度(C语言)详解
广义表的长度 广义表的长度,指的是广义表中所包含的数据元素的个数. 由于广义表中可以同时存储原子和子表两种类型的数据,因此在计算广义表的长度时规定,广义表中存储的每个原子算作一个数据,同样每个子表也只 ...
- noj14求广义表深度
广义表理论上很好理解,但是我感觉对我来说上手还有点困难(还是太菜). 先看广义表的一些定义吧 1 )什么是广义表 广义表,又称列表,也是一种线性存储结构,既可以存储不可再分的元素,也可以存储广义表,记 ...
- 【数据结构】NOJ014 求广义表深度
//[数据结构]NOJ014 求广义表深度 //表头-表尾表示法#include <stdio.h> #include <stdlib.h> #include <stri ...
- noj14 求广义表深度
关键是创建广义表 //求广义表深度 #include <stdio.h> #include <stdlib.h> #include <string.h>typede ...
最新文章
- 分享|如何制作高质量的图文摘要(Graphical Abstract)
- 基于webpack的前端工程化开发解决方案探索(一):动态生成HTML
- 设计模式的理解:组合模式 (Composite)
- mysql数据库引擎调优
- 正确设置JUnit测试名称
- java面试总结(第一天)
- 学会拒绝别人的6个技巧_多少人败在不懂拒绝上!牢记10个高情商拒绝技巧,人生越来越顺...
- Java异常处理课后作业
- 两个八进制小数怎么相加_两个十六进制怎么相加的
- 中芯国际科创板上市发行价定为27.46元/股,募资或超500亿元
- 相加等于目标值的两个数
- IPython 的使用
- AttributeError: module 'labelme.utils' has no attribute 'draw_label'
- web测试app测试接口测试要点整理--最全
- Java学生管理系统-增删改查
- 服务器定时开机设置方法
- 【02】2022.11最新超详细Vuforia图片识别教程
- 基于PyQt开发的第二个小程序:高校BBS发帖辅助软件(CampusBBSAssistant)
- 火车头采集规则,火车头采集数据发布不小心设置了发布数量怎么修改?
- 【能效管理】AcrelEMS-IDC数据中心综合能效管理系统应用分析