数据结构——栈的讲解(超详细)
前言:
小编已经在前面讲完了链表和顺序表的内容,下面我们继续乘胜追击,开始另一个数据结构:栈的详解,下面跟上小编的脚步,开启今天的学习之路!

目录
1.栈的概念和结构
1.1.栈的概念
1.2.栈的结构
2.栈的实现 (此实现是基于顺序表实现的)
2.1.栈的初始化
2.2.栈的销毁
2.3.入栈
2.4.出栈
2.5.取出栈顶的元素
2.6.判断栈中有效的数据个数
2.7.栈元素的打印
3.代码展示
3.1.Stack.h
3.2.Stack.c
总结
正文:
1.栈的概念和结构
1.1.栈的概念
栈是一种特殊的线性表,它只允许一端进一端出,只允许在固定的一端去删除数据和插入数据,对于进行插入和删除操作的地方叫做栈顶,另一端叫做栈底,栈中的数据元素遵从后进先出LIFO的原则,简单来说就是最后一个进的最先出来,这和它的结构有关,下面我们来看一下栈的结构
1.2.栈的结构

上图就是栈的结构图,小编在概念也说过,栈是有栈顶和栈底的,栈顶就是一个出入口,所以我们可以把栈看做成一个罐子,数据只可以从栈顶进行进入和出去,以上就是关于栈的概念和结构了,光知道栈的结构是概念是不够的,下面小编讲带领大家去实现一个栈!

2.栈的实现 (此实现是基于顺序表实现的)
在讲一些栈的功能之前,由于栈是一种线性表,所以我们实现栈的可以有顺序表,链表两种方式来实现,由于时间复杂度等的原因,小编在这里选择用顺序表实现,但这并不代表着我们不可以用链表实现,小编曾经做过题,那个题就让我们用链表来实现栈,可千万不要以为栈只能用顺序表实现,这是重点!下面小编先给各位栈结构体的内容:
typedef int STDataType;
typedef struct stack {STDataType* arr; //数组,类型可能不是一定的所以用typedef替换一下int capacity; //总空间大小int top; //栈顶表示
}ST;
2.1.栈的初始化
我们在每次写一个线性表之前,初始化是必备的操作,因为栈是基于顺序表实现的,所以初始化也顺序表类似,首先我们需要把数组指针先设置为空,对于总空间大小和栈元素个数(栈顶)都得设置为0,由于难度不大,小编就不给各位图演示了,直接上代码:
void STInit(ST* ps)
{ps->arr = NULL;ps->capacity = ps->top = 0; //总空间个数和有用空间个数都初始化为0
}
2.2.栈的销毁
有了初始化操作,自然而然就有着销毁操作,毕竟“有始有终” ,栈的销毁同样也是不难的,我们对于arr,需要判断它是否开辟了空间,如果开辟了就free掉,没有开辟就直接把栈的空间大小和栈顶都置为空就好,下面直接上代码图:
void STDestroy(ST* ps)
{if (ps -> arr) //先判断是否进行动态内存开辟了{free(ps -> arr);}ps->capacity = ps->top = 0;
}
2.3.入栈
在进行完初始化操作以后,就要进行一些正式操作了,看着入栈这个名字很高大尚,以小编的话来说这其实就是栈的尾插(栈也只能尾插,因为只能从栈顶插入),就类似下图:

上面这个图就展示了入栈操作,其实就是我们在顺序表阶段写的尾插操作,首先我们需要先设置一个函数,来判断一下栈的总空间大小和栈顶是否是相等,如果相等了那就扩容,这个和顺序表的扩容是一样的,详情可以看小编之前写的那一篇,由于栈的插入只有入栈这一种,所以扩容操作直接写到函数内部就好,我们在进行完插入以后,直接往栈顶插入数据,然后让栈顶在想后走一步就好了,下面直接展示代码:
void STPush(ST* ps, STDataType x) //类似顺序表的尾插
{if (ps->capacity == ps->top){int newcaopacity = ps->capacity == 0 ? 4 : 2 * ps -> capacity;STDataType* arr1 = (STDataType*)realloc(ps->arr, newcaopacity * sizeof(STDataType));assert(arr1);ps->arr = arr1;ps->capacity = newcaopacity;} //扩容完成ps->arr[ps->top++] = x;
}
2.4.出栈
有入栈肯定就会有出栈,对于栈的出栈,其实就是顺序表的尾删操作,因为栈的元素只能从栈顶出,栈底是不可以出元素的,可以类比下图进行记忆:

通过上图我们就可以知道出栈到底是什么东西,对于出栈,我们首先需要判断栈是不是空的,不然拿什么来出栈?所以此时我们得写一个布尔类型函数来判断一下此时的栈是否是空的,如果是空的返回true,不是真的返回false,此时我们进需要判断栈顶是否为0就好,下面小编直接给代码图:
bool panduan(ST * ps)
{assert(ps);return ps -> top == 0; //这个是来判断栈是不是空了
}
对于上面的代码,小编其实写的很简略,其实如果写麻烦一点我们需要使用选择语句来判断一下是否为空,这里小编直接使用一句话来跳过选择语句了,这个代码的含义就是如果右边是对的那么直接返回true,如果栈顶不为0直接返回false。当我们判断完以后,可以直接进行尾删操作,很简单,我们只需呀让栈顶减一就好了,此时我们就实现了出栈操作,下面给出代码图:
void STPop(ST* ps)
{assert(ps);assert(!panduan(ps));ps->top--;
}
2.5.取出栈顶的元素
这个也是很轻松的,对于取出栈顶的元素,其实就是取顺序表(或者可以直接理解为数组)最后一个有效数据,此时我们还是需要判断栈顶是否还有元素,如果有的话我们直接取出来就好了,可是如果那我们就取出了个寂寞,所以这一步是必须的,之后我们就直接返回栈的最后一个有效数据就好了,下面是代码展示:
STDataType STTop(ST* ps)
{return ps->arr[ps->top - 1];
}
2.6.判断栈中有效的数据个数
这个其实说白了,就是返回栈顶的元素就好了,此时我们也不需要在判断栈是否有数据了,如果没有数据,那就直接返回0就好,下面小编就直接展示代码了:
int STSize(ST* ps)
{return ps->top;
}
2.7.栈元素的打印
对于栈中元素的打印,其实也是有点要求的,可能有些读者朋友会说,我们直接从头打印不就好了,那当然是不行的,这样就违背了我们栈的结构,我们只能从栈顶进入和出去,所以我们打印数据其实就是从栈顶开始进行打印的,我们每进行完一次打印后就让栈顶元素出栈,直到栈中的元素为空就好了,如下图所示:
正如上图所示,打印操作也是这么实现,下面进入代码展示:
void print(ST * ps)
{while (ps.top){printf("%d ", STTop(&ps));STPop(&ps);}
}
以上就是栈结构的实现,其实这么看去,栈是一种比较简单实现的数据结构了(前提学完了顺序表),可能有一些读者朋友想要知道完整的代码,不要着急,下面进入代码展示环节!

3.代码展示
对于栈的实现,小编也是分成了两个文件来进行书写,一个用来声明函数,一个用来实现函数:
3.1.Stack.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h> //存放布尔类型的头文件//下面来复习一下栈的创建
//它的底层代码是数组(也可以理解为顺序表)
typedef int STDataType;
typedef struct stack {STDataType* arr; //数组,类型可能不是一定的所以用typedef替换一下int capacity; //总空间大小int top; //栈顶表示
}ST;//初始化栈
void STInit(ST* ps);//销毁栈
void STDestroy(ST* ps);//入栈
void STPush(ST* ps, STDataType x);//出栈
void STPop(ST* ps);//取出栈顶的元素
STDataType STTop(ST* ps);//获取栈中有效的个数
int STSize(ST* ps);
3.2.Stack.c
#include"Stack.h"
void STInit(ST* ps)
{ps->arr = NULL;ps->capacity = ps->top = 0; //总空间个数和有用空间个数都初始化为0
}void STDestroy(ST* ps)
{if (ps -> arr) //先判断是否进行动态内存开辟了{free(ps -> arr);}ps->capacity = ps->top = 0;
}void STPush(ST* ps, STDataType x) //类似顺序表的尾插
{if (ps->capacity == ps->top){int newcaopacity = ps->capacity == 0 ? 4 : 2 * ps -> capacity;STDataType* arr1 = (STDataType*)realloc(ps->arr, newcaopacity * sizeof(STDataType));assert(arr1);ps->arr = arr1;ps->capacity = newcaopacity;} //扩容完成ps->arr[ps->top++] = x;
}bool panduan(ST * ps)
{assert(ps);return ps -> top == 0; //这个是来判断栈是不是空了
}void STPop(ST* ps)
{assert(ps);assert(!panduan(ps));ps->top--;
}STDataType STTop(ST* ps)
{return ps->arr[ps->top - 1];
}int STSize(ST* ps)
{return ps->top;
}
总结
小编也是完成了对于栈的讲解,总体来说,栈这个数据结构小编自己认为是不算太难的(关于栈的习题不算),本篇文章算是小编最近写的最短的一篇了,希望读者朋友可以去好好的了解,如果文章有什么错误的地方,请在评论区指出,小编一定及时更正,那么我们下篇文章见啦!

相关文章:
数据结构——栈的讲解(超详细)
前言: 小编已经在前面讲完了链表和顺序表的内容,下面我们继续乘胜追击,开始另一个数据结构:栈的详解,下面跟上小编的脚步,开启今天的学习之路! 目录 1.栈的概念和结构 1.1.栈的概念 1.2.栈的结构…...
三防平板助力MES系统,实现工厂移动式生产报工
在当今竞争激烈的制造业环境中,提高生产效率、优化生产流程以及实现精准的生产管理已经成为企业生存和发展的关键。 MES系统作为连接企业计划层和控制层的桥梁,在实现生产过程的信息化、数字化和智能化方面发挥着重要作用。与此同时,三防平板…...
WEB渗透Bypass篇-常规函数绕过
常规函数绕过 <?php echo exec(whoami);?> ------------------------------------------------------ <?php echo shell_exec(whoami);?> ------------------------------------------------------ <?php system(whoami);?> ------------------------…...
C++从入门到起飞之——string类的模拟实现 全方位剖析!
🌈个人主页:秋风起,再归来~🔥系列专栏:C从入门到起飞 🔖克心守己,律己则安 目录 1、多文件之间的关系 2、模拟实现常用的构造函数 2.1 无参构造函数 2.2 有参的构造函数 2.3 析构函…...
数据库国产化大趋势下,还需要学习Oracle吗?
由于众所周知的原因,近两年各行各业都开始了数据库国产化替代的进程,从国外商业数据库替换到国产或者开源数据库,相信很多的数据库从业人员会把部分精力转移到其他数据库产品的学习中,也有一些人在大肆的宣扬Oracle已经过时了&…...
WebLogic
二、WebLogic 2.1 后台弱口令GetShell 漏洞描述 通过弱口令进入后台界面,上传部署war包,getshell 影响范围 全版本(前提后台存在弱口令) 漏洞复现 默认账号密码:weblogic/Oracle123weblogic常用弱口令: Default Passwords | CIRT.net这里注意&am…...
Aspose.Words.dll 插入模板表格,使用的是邮件合并MailMerge功能,数据源是DataTable或list对象,实例
本实例中的实例功能有: 1、 Aspose.Words.dll 插入模板指定域替换为文字或html标签,见1 2、Aspose.Words.dll 插入模板表格,使用的是邮件合并MailMerge功能,数据源是DataTable或List对象(将list转换成DataTable),见1和2 3、word转换Pdf文件,见1 4、将多个word输出文…...
同时打开多个微信
注: 以下方法用到的 D:\微信\WeChat\WeChat.exe是我的电脑微信路径,可右击桌面微信快捷方式 > 属性 > 目标查看 以下方法都需要先关掉已登录的微信后操作 <一> 找到微信路径 新建一个txt文件输入以下内容 start D:\微信\WeChat\WeChat.exe …...
MPU6050的STM32数据读取
目录 1. 概述2. STM32G030对MPU6050的读取3. STM32F1xx对MPU6050的读取 1. 概述 项目中,往往需要根据不同的环境使用不同的芯片处理某些数据,当使用不同的芯片对六轴陀螺仪芯片MPU6050进行数据处理中,硬件的连接、I/O口的设置往往需要根据相…...
【微信小程序开发】——奶茶点餐小程序的制作(二)
👨💻个人主页:开发者-曼亿点 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 曼亿点 原创 👨💻 收录于专栏:…...
Java 文件上传七牛云
Java系列文章目录 文章目录 Java系列文章目录一、前言二、学习内容:三、问题描述四、解决方案:4.1 新建空间4.2 查找密钥4.3 进入开发者中心查找JavaSDK文档4.4 查找文件上传方法4.5 运行测试 五、总结:5.1 学习总结: 一、前言 学…...
大语言模型生成无人系统(如机械臂、无人机等)可以执行的指令序列
大语言模型生成无人系统(如机械臂、无人机等)可以执行的指令序列涉及将自然语言指令转化为具体的、可执行的指令集合。以下是一个详细的流程,展示了如何从自然语言指令生成无人系统的执行指令序列。 1. 输入自然语言指令 用户输入自然语言指…...
尚硅谷谷粒商城项目笔记——十、调试前端项目renren-fast-vue【电脑CPU:AMD】
十、调试前端项目renren-fast-vue 如果遇到其他问题发在评论区,我看到后解决 1 先下载安装git git官网下载地址 2 登录gitee搜索人人开源找到renren-fast-vue复制下载链接。【网课视频中也有详细步骤】 3 下载完成后桌面会出现renren-fast-vue的文件夹 4 开始调…...
Python 的元组和列表的区别是什么?
以下是 Python 中元组(tuple)和列表(list)的主要区别: 1. 语法表示:元组使用小括号 () 来定义,例如 (1, 2, 3) ;列表使用方括号 [] 来定义,例如 [1, 2, 3] 。 2. 可变性…...
【Impala】学习笔记
Impala学习笔记 【一】Impala介绍【1】简介(1)简介(2)优点(3)缺点 【2】架构(1)Impalad(守护进程)(2)Statestore(存储状态…...
视频汇聚平台EasyCVR接入移动执法记录仪,视频无法播放且报错500是什么原因?
GB28181国标视频汇聚平台EasyCVR视频管理系统以其强大的拓展性、灵活的部署方式、高性能的视频能力和智能化的分析能力,为各行各业的视频监控需求提供了优秀的解决方案。视频智能分析平台EasyCVR支持多协议接入,兼容多类型的设备,包括IPC、NV…...
【Linux基础】Linux基本指令(二)
目录 🚀前言一,mv指令二,more & less指令2.1 more 指令2.1 less指令 三,重定向技术(重要)3.1 echo指令3.2 输出重定向 >3.3 追加重定向 >>3.4 输入重定向 < 四,head & tail指令4.1 head 指令4.2 t…...
全面介绍 Apache Doris 数据灾备恢复机制及使用示例
引言 Apache Doris 作为一款 OLAP 实时数据仓库,在越来越多的中大型企业中逐步占据着主数仓这样的重要位置,主数仓不同于 OLAP 查询引擎的场景定位,对于数据的灾备恢复机制有比较高的要求,本篇就让我们全面的介绍和示范如何利用这…...
Python pandas常见函数
Pandas库 基本概念读取数据数据处理数据输出其他常用功能 pip install pandas基本概念 数据结构 Series: 一维数据结构 import pandas as pd data pd.Series([10, 20, 30, 40], index[a, b, c, d]) print(data)DataFrame: 二维数据结构 data {Name: [Alice, Bob, Charlie],Ag…...
行业落地分享:阿里云搜索RAG应用实践
最近这一两周看到不少互联网公司都已经开始秋招提前批了。 不同以往的是,当前职场环境已不再是那个双向奔赴时代了。求职者在变多,HC 在变少,岗位要求还更高了。 最近,我们又陆续整理了很多大厂的面试题,帮助一些球友…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
