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;

结点的结构:

  1. 标志域 tag用于区分原子结点和表结点。
  2. 指针域 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;}}
}

分三种情况

  1. 传入一个空指针,则建立空表。
  2. 若传入一个字符,则建立一个只有原子的结点的广义表。
  3. 否则,则进行如下操作:
    脱去外层括号;
    从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);
}

递归定义为:

  1. 当L为空表时,深度为1;
  2. 当L为原子时,深度为0;
  3. 归纳: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. 求广义表的深度代码解读

    广义表的头节点必定是1. int ListsDepth (Lslink LS) //广义表采用单链结构 { int max=0; //默认情况下,认为表if (LS->atom==0) retu ...

  2. 广义表-求广义表深度,建立广义表,复制广义表

    广义表-求广义表深度,建立广义表,复制广义表 例: 广义表(a,(a,b),d,e,((i,j),k)) 求广义表的长度和深度 长度为5,深度为3 长度:有效逗号个数+1 深度:有效括号个数 求广义表 ...

  3. 数据结构14——求广义表深度(严5.30)

    Description 试按表头.表尾的分析方法编写求广义表的深度的递归程序. Input 输入一串以'('开始,以'('结束的字符串,并且输入的左右括号必须匹配,如:(),(())-- Output ...

  4. 求广义表深度(严5.30)

    Description 试按表头.表尾的分析方法编写求广义表的深度的递归程序. Input 输入一串以'('开始,以'('结束的字符串,并且输入的左右括号必须匹配,如:(),(())-- Output ...

  5. 西北工业大学NOJ数据结构—014求广义表深度

    #include <stdio.h> #include <stdlib.h>typedef struct Node {int A_L;//使用枚举不熟练,A_T代表Atom或L ...

  6. 广义表的深度和长度(C语言)详解

    广义表的长度 广义表的长度,指的是广义表中所包含的数据元素的个数. 由于广义表中可以同时存储原子和子表两种类型的数据,因此在计算广义表的长度时规定,广义表中存储的每个原子算作一个数据,同样每个子表也只 ...

  7. noj14求广义表深度

    广义表理论上很好理解,但是我感觉对我来说上手还有点困难(还是太菜). 先看广义表的一些定义吧 1 )什么是广义表 广义表,又称列表,也是一种线性存储结构,既可以存储不可再分的元素,也可以存储广义表,记 ...

  8. 【数据结构】NOJ014 求广义表深度

    //[数据结构]NOJ014 求广义表深度 //表头-表尾表示法#include <stdio.h> #include <stdlib.h> #include <stri ...

  9. noj14 求广义表深度

    关键是创建广义表 //求广义表深度 #include <stdio.h> #include <stdlib.h> #include <string.h>typede ...

最新文章

  1. 分享|如何制作高质量的图文摘要(Graphical Abstract)
  2. 基于webpack的前端工程化开发解决方案探索(一):动态生成HTML
  3. 设计模式的理解:组合模式 (Composite)
  4. mysql数据库引擎调优
  5. 正确设置JUnit测试名称
  6. java面试总结(第一天)
  7. 学会拒绝别人的6个技巧_多少人败在不懂拒绝上!牢记10个高情商拒绝技巧,人生越来越顺...
  8. Java异常处理课后作业
  9. 两个八进制小数怎么相加_两个十六进制怎么相加的
  10. 中芯国际科创板上市发行价定为27.46元/股,募资或超500亿元
  11. 相加等于目标值的两个数
  12. IPython 的使用
  13. AttributeError: module 'labelme.utils' has no attribute 'draw_label'
  14. web测试app测试接口测试要点整理--最全
  15. Java学生管理系统-增删改查
  16. 服务器定时开机设置方法
  17. 【02】2022.11最新超详细Vuforia图片识别教程
  18. 基于PyQt开发的第二个小程序:高校BBS发帖辅助软件(CampusBBSAssistant)
  19. 火车头采集规则,火车头采集数据发布不小心设置了发布数量怎么修改?
  20. 【能效管理】AcrelEMS-IDC数据中心综合能效管理系统应用分析

热门文章

  1. Java源码-弹球小游戏(Pin Ball)
  2. Type C --- 引脚图解
  3. 九、(补充文章四)Arcgis实现深度学习训练样本数据的批量制作——只靠原图+shp如何批量制作样本图片
  4. Linux源码编译安装Postgres
  5. 陶哲轩实分析:有理数和整数理论体系统一
  6. 一些可以显著提高大型 Java 项目启动速度的尝试
  7. 怎样在一只股票上做T+0?
  8. QTableView根据内容自动调整列宽行高
  9. Delta Lake 0.5.0 新功能介绍
  10. 数据服务: 基于ApiJson作为数据服务底层引擎的调研