C++广义表的介绍及创建方法-附C语言实现代码

1. 简介

数组可以存储不允许再分割的数据元素,如字符’X’,数字11,当然它也可以存储数组,二维数组就是一个例子,你可以理解二维数组的每一行的元素是一列中的对应元素的组合。

广义表是一种线性表,或者说,广义表是一种线性表的推广,它属于多层次的线性表,广义表中可以存储不可以再分割的元素,同时也可以存储一张广义表(子表),因此适用情况相对灵活。

设ai为广义表的第i个元素,广义表是n(n≥0)个元素的一个序列,若n=0时则称为空表。广义表GL的一般表示与线性表相同,即:

GL=(a1,a2,…,ai,…,an)

其中n表示广义表的长度,即广义表中所含元素的个数,n≥0。如果ai是单个数据元素,则ai是广义表GL的原子;如果ai是一个广义表,则ai是广义表GL的子表。

一般来说,广义表具有如下重要的特性:

(1)广义表中的数据元素有相对次序

(2)广义表的长度定义为最外层包含元素个数

(3)广义表的深度定义为所含括弧的重数。其中原子的深度为0,空表的深度为1

(4)广义表可以共享;一个广义表可以为其他广义表共享;这种共享广义表称为再入表

(5)广义表可以是一个递归的表。一个广义表可以是自已的子表。这种广义表称为递归表。递归表的深度是无穷值,长度是有限值

(6)任何一个非空广义表GL均可分解为表头head(GL) = a1和表尾tail(GL) = ( a2,…,an) 两部分。

2. 广义表的结点设计

我们以常规方法来看,广义表是一种不定规模的数据结构,很难为之分配具体的空间,因此创建的方法采用动态的链式方法,动态的创建空间。

如图:

23e23eb5b43541cb8d9b72ef96902c48.png

对于每一个结点而言由如上三大部分组成,其中Tag域为标志字段,其只有两个参数,0或者1(Tag域使用int类型,在某些情况下因为只需要简单判断也可以使用更短的类型,如bool);Atom/Node域的内容由tag标志决定,当Tag为0时表示该节点是原子结点(即存放原子数据),当Tag为1时表示该节点为指向下一个广义表的指针(即表结点),Link域存放与本元素同一层的下一个元素所在的结点地址,当本元素时所在层的最后一个元素时,Link域为NULL;

链式法设计:

#define AtomType int
typedef enum{ATOM,LIST}ElemTag; //ATOM = 0:原子;LIST = 1:子表 
/*结点设计*/
typedef struct GLNode{ElemTag tag; //枚举类型的标志域,只能取定义了的枚举值union{   //union联合体,下面两部分只能取其一;要么取AtomType;要么取结构体ptr,ptr包括两个指针hp,tp AtomType atom;struct{struct GLNode *hp,*tp;}ptr;}; 
}*GList; //定义广义表类型,GList为指针

下面是子表法设计:

/*线性表存储之扩展线性表 = 子表法*/ 
typedef struct GLNode{ElemTag tag;union{AtomType atom;struct GLNode *hp;    //对于列表,hp指向本列表内部第一个元素,而tp是指向本层次上的下一个元素 };                        struct GLNode *tp;
} *GList;

首先定义AtomType的数据类型,可以为基本的int型,也可以为一些其他的数据类型,包括简单的char或者是复杂一些的结构体,不过这里不建议创建过于复杂的结构体。

其次,关于tag域的建立,我们可以使用一个枚举建立,分别表示Atom/Node到底取何种值,而关于Atom/Node域,则可以建立一个union(共用体)来表示,共用体公用内存空间,只能取其一赋值,这也符合广义表的基本需求;而关于表达的Link域,我们使用链式的存储方法可以化简,而使用子表的方式则必须表达。

3. 广义表的创建

如图所示,广义表的每一个结点相互串联,有些结点存储原子数据,有些结点则存储另一份广义表数据,我们创建数据string ss = "(2,3,4, (1, (3, ( 7,8 ) ),2) )";其基本可以分成4层,每一个层中一个括号表示下一层,在数学表示中,我们也常用括号的级数表示广义表。

 e772e415fae64554ad91d6fca82f66cf.png

 因此,广义表的创建就需要进行连接,连接的方法是更具tag进行判断本结点中是Atom(原子)还是Node(结点),再根据其中的选择进行相对应的连接,可以由如下图可知。

732f2d0b373b452f9894061b3ffc073c.png

 对于代码的书写,我们首先需要对传入的字符串进行切割,将每一组括号”()”进行分割,每一组括号其中就表示的一份新的广义表,我们需要找到括号并且与这个括号相互匹配的括号数进行对应,找到并切割掉,以此分离出表头串,方便我们进行后续的操作。

void sever(string &str,string &hstr){//将非空串str分割成两部分,hstr是表头int n = str.size();int i = -1;int k = 0; //k记录尚未配对的“(” 数char ch;    do{ //搜索最外层第一个( ++i;ch = str[i];if(ch == '(') ++k;else if(ch == ')') --k;}while(i<n&&(ch != ','||k!=0));if(i<n){hstr =str.substr(0,i);str = str.substr(i+1,n-i-1);}else{hstr = str.substr(0,str.size());str.clear();}
}

我们通过分割以后可以通过上文介绍的方法进行指针的相互指引,核心就是要注意tag的判断,以及Atom/Node域是使用共用体创建的,要注意两者的空间不可以重叠,严格使用if(){}else{}的语法结构不要乱套。

void CreateGList(GList &L,string s){//采用头尾链表存储结构,创建Lif(s.compare(emp) == 0) L = NULL;else{L = (GList)malloc(sizeof(GLNode));if(!L) exit(0);if(s.size() == 1){ //单个元素,建立原子节点 L->tag = ATOM;L->atom = s[0];}else{ //表节点 ,表尾 L->tag = LIST;GList p,q;p = L; //p是指向当前子表(表尾节点)的指针 string sub;sub = s.substr(1,s.size()-2); //去掉外层括号 string hsub;do{ //重复建立n个子表 sever(sub,hsub); //sub中分理出表头串hsub ,同时,sub去除了hsubCreateGList(p->ptr.hp,hsub);q = p; //记录p,下面sub不为空,要再建立一个表尾节点,q记录上一层的p,用以连接q->ptr.tp = q if(!sub.empty()) {p = (GList)malloc(sizeof(GLNode));if(!p)exit(0);p -> tag = LIST;q -> ptr.tp = p;}}while(!sub.empty());q -> ptr.tp = NULL;}}
}

4. 广义表的深度

我们只需要根据表的情况进行一个递归调用即可判断,当然需要特判一下空表的情况。

int GListDepth(GList L) {if(!L) return 1; //空表1if(L->tag ==ATOM ) return 0;GList pp;//遍历同一层,递归下一层,取表尾,取表头,第一步先去一个表头 int max;for(max = 0, pp =L;pp!=NULL;pp = pp->ptr.tp){int dep = GListDepth(pp->ptr.hp) ;if(dep > max) max = dep; //这一步比较,是比较同一层的depth }return max+1;
}

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/142142.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

JVM HotSpot 虚拟机: 对象的创建, 内存布局和访问定位

目录 前言 对象的创建 对象的内存布局 对象的访问定位 前言 了解JVM的内存区域划分之后, 也大致了解了java程序的内存分布模型, 也了解它里面的内存区域里面的类型和各个类型的作用, 接下来我们进一步从对象创建到访问的角度, 来看看这些内存区域之间是怎么关联起来的. …

2023高教社杯全国大学生数学建模竞赛C题 Python代码演示

目录 问题一1.1 蔬菜类商品不同品类或不同单品之间可能存在一定的关联关系&#xff0c;请分析蔬菜各品类及单品销售量的分布规律及相互关系。数据预处理数据合并提取年、月、日信息对蔬菜的各品类按月求销量均值 季节性时间序列分解STL分解加法分解乘法分解 ARIMALSTM import p…

什么是代理IP_如何建立代理IP池?

什么是代理IP_如何建立代理IP池&#xff1f; 1. 概述1.1 什么是代理IP&#xff1f;1.2 代理IP的工作原理1.3 爬虫的应用场景1.3.1 搜索引擎&#xff0c;最大的爬虫1.3.2 数据采集&#xff0c;市场分析利器1.3.3 舆情监控&#xff0c;品牌营销手段1.3.4 价格监测&#xff0c;全网…

时序差分法

一、时序差分法 时序差分是一种用来估计一个策略的价值函数的方法&#xff0c;它结合了蒙特卡洛和动态规划算法的思想。时序差分方法和蒙特卡洛的相似之处在于可以从样本数据中学习&#xff0c;不需要事先知道环境&#xff1b;和动态 规划的相似之处在于根据贝尔曼方程的思想&…

外网(公网)访问VMware workstation 虚拟机内web网站的配置方法---端口转发总是不成功的原因

问题背景&#xff1a;客户提供的服务器操作系统配置web程序时&#xff0c;总是显示莫名其妙的问题&#xff0c;发现是高版本操作系统的.net库已经对低版本.net库进行了大范围修订&#xff0c;导致在安全检测上、软件代码规范上更加苛刻&#xff0c;最终导致部署不成功。于是想到…

【C++】入门基础(下)

Hi&#xff01;很高兴见到你~ 目录 7、引用 7.3 引用的使用&#xff08;实例&#xff09; 7.4 const引用 【第一分点】 【第二分点1】 【第二分点2】 7.5 指针和引用的关系&#xff08;面试点&#xff09; 8、inline 9、nullptr Relaxing Time&#xff01; ———…

基于VUE的老年颐养中心系统的设计与实现计算机毕业论文

根据联合国的预测&#xff0c;2000-2050年将是我国人口年龄结构急剧老化的阶段&#xff0c;老化过程大致也可分为三个阶段&#xff1a;第一阶段&#xff0c;65岁及以上人口比例从2000年的6.97%上升到2020年的11.7%&#xff0c;20年时间仅上升4.63个百分点。第二阶段为2020-2040…

蓝桥杯省赛真题——大臣的旅费

输入样例&#xff1a; 5 1 2 2 1 3 1 2 4 5 2 5 4 输出样例&#xff1a; 135分析&#xff1a; 本题实际上要求我们去求在图中最远两点之间的距离&#xff0c;也就是树的直径 我们先从某一个点出发&#xff0c;到达离其最远的点&#xff0c;然后再重复操作一次即可 #inclu…

钢轨缺陷检测-目标检测数据集(包括VOC格式、YOLO格式)

钢轨缺陷检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1h7Dc0MiiRgtd7524cBUOFQ?pwdfr9y 提取码&#xff1a;fr9y 数据集信息介绍&#xff1a; 共有 1493 张图像和一一对应的标注文件 标…

【二叉树进阶】二叉搜索树

目录 1. 二叉搜索树概念 2. 二叉搜索树的实现 2.1 创建二叉搜索树节点 2.2 创建实现二叉搜索树 2.3 二叉搜索树的查找 2.4 二叉搜索树的插入 2.5 二叉搜索树的删除 2.6 中序遍历 2.7 完整代码加测试 3. 二叉搜索树的应用 3.1 K模型&#xff1a; 3.2 KV模型&#xf…

数据技术革命来袭!从仓库到飞轮,企业数字化的终极进化!

文章目录 数据仓库&#xff1a;信息化的基石数据中台&#xff1a;数字化转型的加速器数据飞轮&#xff1a;智能化的新纪元技术演进的驱动力 自20世纪80年代末数据仓库问世以来&#xff0c;它迅速成为企业数据管理的核心。作为一名大数据工程师&#xff0c;我深刻体会到数据仓库…

k8s使用本地docker私服启动自制的flink集群

目标&#xff1a;使用本地flink环境自制flink镜像包上传到本地的私服&#xff0c;然后k8s使用本地的私服拉取镜像启动Flink集群 1、将本地的flink软件包打包成Docker镜像 从官网下载flink-1.13.6的安装包&#xff0c;修改其中的flink-conf.yaml&#xff0c;修改下面几项配置 …

Mistral AI再创新高,Pixtral 12B多模态模型强势来袭

前沿科技速递&#x1f680; 近日&#xff0c;Mistral AI 发布了其首款多模态大模型——Pixtral 12B。作为一款具有语言与视觉处理能力的模型&#xff0c;Pixtral 12B 支持高达10241024像素的图像&#xff0c;具备强大的文本生成、图像理解与生成能力&#xff0c;能够处理复杂的…

热成像目标检测数据集

热成像目标检测数据集 V2 版本 项目背景 热成像技术因其在安防监控、夜间巡逻、消防救援等领域的独特优势而受到重视。本数据集旨在提供高质量的热成像图像及其对应的可见光图像&#xff0c;支持热成像目标检测的研究与应用。 数据集概述 名称&#xff1a;热成像目标检测数据…

Kafka日志索引详解与常见问题分析

目录 一、Kafka的Log日志梳理 1、Topic下的消息是如何存储的&#xff1f; 1. log文件追加记录所有消息 2. index和timeindex加速读取log消息日志 2、文件清理机制 1. 如何判断哪些日志文件过期了 2. 过期的日志文件如何处理 3、Kafka的文件高效读写机制 1. Kafka的文件…

图神经网络模型扩展(5)--2

1.图的无监督学习 在数据爆炸的时代&#xff0c;大部分数据都是没有标签的。为了将它们应用到深度学习模型上&#xff0c;需要大量的人力来标注数据&#xff0c;例如我们熟知的人脸识别项目&#xff0c;如果想取得更好的识别效果&#xff0c;则一定需要大量人工标注的人脸数据。…

Android MediaPlayer + GLSurfaceView 播放视频

Android使用OpenGL 播放视频 概述TextureView的优缺点OpenGL的优缺点 实现复杂图形效果的场景参考 概述 在Android开发中&#xff0c;使用OpenGL ES来渲染视频是一种常见的需求&#xff0c;尤其是在需要实现自定义的视频播放界面或者视频特效时。结合MediaPlayer&#xff0c;我…

【论文阅读】BC-Z: Zero-Shot Task Generalization with Robotic Imitation Learning

Abstract 在这篇论文中&#xff0c;我们研究了使基于视觉的机器人操纵系统能够泛化到新任务的问题&#xff0c;这是机器人学习中的一个长期挑战。我们从模仿学习的角度来应对这一挑战&#xff0c;旨在研究如何扩展和扩大收集的数据来促进这种泛化。为此&#xff0c;我们开发了…

数据库之索引<保姆级文章>

目录&#xff1a; 一. 什么是索引 二. 索引应该选择哪种数据结构 三. MySQL中的页 四. 索引分类及使用 一. 什么是索引&#xff1a; 1. MySQL的索引是⼀种数据结构&#xff0c;它可以帮助数据库高效地查询、更新数据表中的数据。 索引通过 ⼀定的规则排列数据表中的记录&#x…

F28335 时钟及控制系统

1 F28335 系统时钟来源 1.1 振荡器OSC与锁相环PLL 时钟信号对于DSP来说是非常重要的,它为DSP工作提供一个稳定的机器周期从而使系统能够正常运行。时钟系统犹如人的心脏,一旦有问题整个系统就崩溃。DSP 属于数字信号处理器, 它正常工作也必须为其提供时钟信号。那么这个时钟…