【数据结构】栈和队列(上)
目录
一、栈(先进后出、后进先出的线性表)
1、栈的概念及结构
2、栈的底层结构分析
二、代码实现
1、定义一个栈
2、栈的初始化
3、入栈
3、增容
4、出栈
5、取栈顶
6、销毁栈
一、栈(先进后出、后进先出的线性表)
1、栈的概念及结构
栈:一种特殊的线性表,只允许在固定的一端进行插入和删除数据的操作。进行数据插入、删除的一端为栈顶,不可进行操作的一端则是栈底。对于任意一个数据结构,我们都要分析一下它的逻辑结构和物理结构,既然是线性表,那么说明逻辑结构一定是线性的
逻辑结构:是线性的
物理结构:也是线性的
对于栈的操作主要有如下两个:
一个是压栈,另一个则是出栈。其中压栈是栈的插入操作(也叫做进栈、入栈);出栈则是栈的删除操作,出数据也在栈顶。
2、栈的底层结构分析
既然我们已经对栈这一个数据结构的概念有了初步的了解,那么现在,我们来深入探讨一下,栈的底层结构是什么?既然他是线性的,那么他是数组还是链表呢?
我们从这里分析:
我们可以从上图看到链表的结构,由于栈只能从栈顶操作数据,假设栈的底层是链表,如果链表的尾部为栈顶的话,每一次访问栈顶都要去遍历一次链表,那么无疑使时间复杂度增加到了O(N),相反,如果链表的头部为栈顶,对数据进行插入删除时的时间复杂度就会好很多,为O(1)。
我们来画个图看看数组,从数组中插入删除数据,可以把数组的尾当做栈顶插入删除数据,时间复杂度认为O(1),既然这样,链表和数组作为栈的底层结构,入栈和出栈的时间复杂度都为O(1),那么,我们来换个维度来考虑:
以上是使用链表和数组结构写的栈的构造代码,我们可以看出,左图中的结构使用了链表,每向栈中插入一个数据,空间不仅仅会增加int类型的4字节,还会增加指针8字节的大小,相比于数组结构,链表结构对空间的使用会更大,所以,我们还是更推荐用数组作为栈的底层结构。
二、代码实现
下面,我们来实现一下栈的代码:
1、定义一个栈
我们要定义一下栈的结构,由于栈的底层是数组,又要开辟空间,我们就定义一个动态的数组好了:
typedef int STDataType;
typedef struct Stack
{STDataType* arr;int top;int capacity;
}ST;
2、栈的初始化
下面,我们来定义一个初始化方法:
void StackInit(ST* ps)
{ps->arr = NULL;ps->top = ps->capacity = 0;
}
3、入栈
当要向数组插入数据首先要看栈中是否为空,若不为空,插入数据后ps->top要++,指向栈顶
3、增容
注意:这里又出现一个问题,当ps->top==ps->capacity时,说明空间已经不够了,如果要继续插入数据,我们需要进行一个增容操作:
这里,ps->capacity=newcapacity
void StackPush(ST* ps,STDatatype x)
{assert(ps);//这里做一个断言操作,防止对空指针解引用if(ps->top == ps->capacity){int newcapacity = ps->capacity==0?4:2*ps->capacity;(STDataType*)tmp = (STDataType*)realloc(ps->arr,newcapacity*sizeof(STDataType));if(tmp == NULL){perror("realloc fail!");exit(1); }ps->arr = tmp;ps->capacity = newcapacity;}ps->arr[ps->top++] = x;
}
4、出栈
出栈操作:
每当遇到数据结构中的出数据操作时,我们都要考虑其是否有数据可以为我们所用,所以写出栈操作之前,我们首先要判断栈是否为空,这里,我们可以定义一个方法:
bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;//判断top(即有效数据个数是否为零,如果为零,则返回ture)
}
其次,假设,ps->top,不为零,则出栈操作直接可以写成--ps->top;
void Stackpop(ST* ps)
{assert(ps);if(!StackEmpty(ps)){--ps->top; }
}
5、取栈顶
下一个操作是:取栈顶操作,与出栈顶(有效的数据个数会减少)操作不同,去栈顶操作不会删除数据,而只是将栈顶的数据复制一下并使用。
STDataType StackTop(ST* ps)
{assert(!StackEmpty(ps);return ps->arr[ps->top-1];
}
6、销毁栈
接下来,我们看一下对于栈的销毁操作:
void StackDestroy(ST* ps)
{if(ps->arr)free(ps->arr);ps->arr = NULL;//这里有一点ps->top = ps->capacity = 0;
}
这里有一个小tips:将ps->arr = NULL,这里可能有同学会有疑问,为什么写出栈操作时,只需要--ps->top,不需要将数据free,这是因为,在数组中,arr表示数组首元素的地址,如果你将ps->arr free掉,那么整个数组的数据都会被销毁,而链表的每一个空间都是独立存在的,假设你将上一个结点的空间销毁了,不会影响下一个结点,数组则不然。
以下是测试代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"void test01()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 5);/*StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);*//*while (!StackEmpty(&st)){int top = StackTop(&st);printf("%d ", top);StackPop(&st);}*/int size = StackSize(&st);printf("size:%d", size);StackDestroy(&st);
}int main()
{test01();return 0;
}
相关文章:

【数据结构】栈和队列(上)
目录 一、栈(先进后出、后进先出的线性表) 1、栈的概念及结构 2、栈的底层结构分析 二、代码实现 1、定义一个栈 2、栈的初始化 3、入栈 3、增容 4、出栈 5、取栈顶 6、销毁栈 一、栈(先进后出、后进先出的线性表) 1、…...

科技赋能·长效治理|无忧树建筑修缮渗漏水长效治理交流会圆满举行!
聚焦行业痛点,共话长效未来!5月16日,由无忧树主办的主题为“科技赋能长效治理”的建筑修缮渗漏水长效治理技术交流会在上海圆满举行。来自全国的建筑企业代表、专家学者、技术精英齐聚一堂,共探渗漏治理前沿技术,见证科…...

【闲聊篇】java好丰富!
1、在学习mybatis-plus的文档时,发现引入了solon依赖,才发现这是一个对标spring生态的框架,有意思! 还有若依框架,真的好丰富~~~~~~~ 2、今天面试官问我,他说很少遇到用redission做延迟队列的。后面我就反…...
STL中list的模拟
这里写目录标题 list 的节点 —— ListNodelist 的 “导览员” —— ListIteratorlist 的核心 —— list 类构造函数迭代器相关操作容量相关操作 结尾 在 C 的 STL(标准模板库)中,list 是一个十分重要的容器,它就像一个灵活的弹簧…...

6.3.2图的深度优先遍历
知识总览: 树的先根遍历: 采用递归一直找某个节点的子树直到找不到从上往下找 访问根节点1,1的子树有2、3、4,访问2,2节点子树有5访问5,5没有子树,退回到2,2还有子树6访问6,6没有子树再退回到2,2的子树都被访问了再退…...

畅游Diffusion数字人(30):情绪化数字人视频生成
畅游Diffusion数字人(0):专栏文章导航 前言:仅从音频生成此类运动极具挑战性,因为它在音频和运动之间存在一对多的相关性。运动视频的情绪是多元化的选择,之前的工作很少考虑情绪化的数字人生成。今天解读一个最新的工作FLOAT,可以生成制定情绪化的数字人视频。 目录 贡献…...

UE5 Va Res发送请求、处理请求、json使用
文章目录 介绍发送一个Get请求发送Post请求设置请求头请求体带添json发送请求完整的发送蓝图 处理收到的数据常用的json处理节点 介绍 UE5 自带的Http插件,插件内自带json解析功能 发送一个Get请求 只能写在事件图表里 发送Post请求 只能写在事件图表里 设置…...
关于flutter中Scaffold.of(context).openEndDrawer();不生效问题
原因: 在 Flutter 中,Scaffold.of(context) 会沿着当前的 context 向上查找最近的 Scaffold。如果当前的 widget 树层级中没有合适的 Scaffold(比如按钮所在的 context 是在某个子 widget 中),就找不到它。 解决办法…...
【C++】深入理解C++中的函数与运算符重载
文章目录 前言一、什么是重载?1.1 函数重载1.1.1 函数重载的规则1.1.2 示例:函数重载 1.2 运算符重载1.2.1 运算符重载的规则1.2.2 示例:运算符重载 1.2.3 运算符重载的注意事项 二、重载的注意事项2.1 重载的二义性2.2 默认参数和重载2.3 运…...

【读代码】BAGEL:统一多模态理解与生成的模型
一、项目概览 1.1 核心定位 BAGEL是字节跳动推出的开源多模态基础模型,具有70亿激活参数(140亿总参数)。该模型在统一架构下实现了三大核心能力: 多模态理解:在MME、MMBench等9大评测基准中超越Qwen2.5-VL等主流模型文本生成图像:生成质量媲美SD3等专业生成模型智能图像…...

隧道自动化监测解决方案
行业现状 隧道作为一种重要的交通运输通道,不管是缓解交通压力,还是让路网结构更趋于完善,它都有着不可估量的作用。隧道在运营过程中,由于受到材料退化、地震、人为因素等影响会发生隧道主体结构的损坏和劣化。若不及时检修和维护…...
如何通过EventChannel实现Flutter与原生平台的双向通信?
在Flutter开发中,EventChannel是处理单向数据流的核心组件,尤其适用于原生平台(Android/iOS)主动向Flutter端推送实时数据的场景,例如传感器数据、后台任务通知等。虽然EventChannel本身以原生到Flutter的单向通信为主,但结合特定设计模式,仍可实现双向交互。本文将详细…...

游戏引擎学习第307天:排序组可视化
简短谈谈直播编程的一些好处。 上次结束后,很多人都指出代码中存在一个拼写错误,因此这次我们一开始就知道有一个 bug 等待修复,省去了调试寻找错误的时间。 今天的任务就是修复这个已知 bug,然后继续排查其他潜在的问题。如果短…...

java接口自动化初识
简介 了解什么是接口和为什么要做接口测试。并且知道接口自动化测试应该学习哪些技术以及接口自动化测试的落地过程。 一、什么是接口 在这里我举了一个比较生活化的例子,比如我们有一台笔记本,在笔记本的两端有很多插口。例如:USB插口。那…...
工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求
前言 大家好,我是老马。 最近想设计一款审批系统,于是了解一下关于流程引擎的知识。 下面是一些的流程引擎相关资料。 工作流引擎系列 工作流引擎-00-流程引擎概览 工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎&#x…...
时序数据库IoTDB的分片与负载均衡策略深入解析
一、引言 随着数据库服务的业务负载增加,扩展服务资源成为必然需求。扩展方式主要分为纵向扩展和横向扩展。纵向扩展通过增加单台机器的能力(如内存、硬盘、处理器)来实现,但受限于单台机器的硬件能力。而横向扩展则通过增加更多…...

NVM安装使用及问题解决
目录 一、前言 二、NVM安装 三、配置下载源 四、nvm使用 五、安装nvm list available没有的版本 六、问题解决 一、前言 如果你开发 Node.js 项目,可能会遇到这些问题: ①新项目需要 Node.js 18,但老项目只能用 Node.js 14,…...

C++学习之STL学习:string类使用
在之前的学习中,我们初步了解到了STL的概念,接下来我们将深入学习STL中的string类的使用,后续还会结合他们的功能进行模拟实验 目录 为什么要学习string类? 标准库中的string类 string类(了解) auto和范围…...
基于 STC89C52 的养殖场智能温控系统设计与实现
摘要 本文提出一种基于 STC89C52 单片机的养殖场环境温度智能控制系统,通过集成高精度温度传感器、智能执行机构及人机交互模块,实现对养殖环境的实时监测与自动调控。系统具备温度阈值设定、超限报警及多模式控制功能,可有效提升养殖环境稳定性,降低能耗与人工成本。 一…...
redis哨兵服务
配置主机Host67为master服务器配置主机host68为 slave服务器配置主机host69运行哨兵服务测试配置 IP地址主机名192.168.10.167redis167192.168.10.168redis168192.168.10.169redis169 步骤一:配置主机Host67为master服务器 [rootredis169 ~]# vim /etc/redis.c…...

5月24日day35打卡
模型可视化与推理 知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 作业:调整模型定义时的超参数&#x…...
嵌入式<style>设计模式
每天分享一个web前端开发技巧。 今天分享的主题是,如何提升前端代码的内聚性。我们在写<style></style>的时候,往往把大量无关联的样式写在同一个<style>下,而且离相关的html元素很远,这样导致每次想修改某个元…...
Kotlin 中该如何安全地处理可空类型?
在 Kotlin 中,可空类型(如 String?)是语言设计的核心特性之一,旨在从编译时避免 NullPointerException(NPE)。 1 核心处理方式 1.1 安全调用操作符(?.) 直接调用可空对象的方法…...
基于大模型预测的视神经脊髓炎技术方案
目录 一、术前评估与预测1. 数据采集与预处理2. 大模型构建与训练3. 术前风险评估与预测二、术中监测与决策支持1. 实时数据采集与传输2. 术中决策支持系统三、术后管理与康复1. 术后早期预警与监测2. 康复效果预测与个性化方案四、并发症风险预测与防控1. 并发症风险预测模型2…...
使用防火墙禁止程序联网(这里禁止vscode)
everything搜一下Code.exe的安装路径:D:\downloadApp1\vscode\Microsoft VS Code\Code.exe 方法:使用系统防火墙(推荐) Windows 通过防火墙阻止 VS Code: 打开 Windows Defender 防火墙(控制面板 > 系统…...

Linux(7)——进程(概念篇)
目录 一、基本概念 二、描述进程——PCB 1.task_struct——PCB的一种 2.task_struct的内容分类 三、查看进程 1.通过系统目录查看 2.通过ps命令查看 四、通过系统调用获取进程的PID和PPID 五、通过系统调用创建进程 1.fork函数创建子进程 2.使用if来引出问题 六、L…...

前端流行框架Vue3教程:24.动态组件
24.动态组件 有些场景会需要在两个组件间来回切换,比如 Tab 界面 我们准备好A B两个组件ComponentA ComponentA App.vue代码如下: <script> import ComponentA from "./components/ComponentA.vue" import ComponentB from "./…...

Unity3D仿星露谷物语开发48之显示树桩效果
1、目标 砍完橡树之后会露出树桩,然后树桩可以用斧头收割,并将创建一个新的砍树桩的粒子效果。 这里有:一种作物收获后创造另一种作物的逻辑。 2、分析 在SO_CropDetailsList中,Harvested Transform Item Code可以指定收获后生…...

[Datagear] 实现按月颗粒度选择日期的方案
在使用 Datagear 构建数据分析报表时,常常会遇到一个问题:如果数据的目标颗粒度是“月”,默认的日期控件却是精确到“日”的,这在用户交互和数据处理层面会带来不必要的复杂度。本文将分享两种解决方案,帮助你更好地控制日期控件的颗粒度,实现以月为单位的日期筛选功能。…...

漏洞检测与渗透检验在功能及范围上究竟有何显著差异?
漏洞检测与渗透检验是确保系统安全的重要途径,这两种方法各具特色和功效,它们在功能上有着显著的差异。 目的不同 漏洞扫描的主要任务是揭示系统内已知的安全漏洞和隐患,这就像是对系统进行一次全面的健康检查,看是否有已知的疾…...