当前位置: 首页 > news >正文

【数据结构】栈

文章目录

  • 😺前言
  • 栈初始化
  • 栈顶入栈
  • 栈顶出栈
  • 栈体判空
  • 栈的数据个数
  • 获取栈顶元素
  • 栈的销毁
  • 整体代码
  • 😼写在最后

😺前言

  • 👻前面我们学习了链表,总算是跨过一个台阶了,本章带大家轻松一波,领悟一下栈的魅力。
  • 🤡栈是一种较为简单的数据结构,它的主要性质,就是数据后进先出(LIFO),我们可以利用这一性质,在做某些算法题时,以此为切入点。因此,栈还是挺不错的。

栈初始化

  • 栈的性质是后进先出(不能任意插入删除),并且只能访问栈顶元素,因此,对数据的入栈和出栈是特别方便的。

在这里插入图片描述

  • 根据栈的这样一个后进先出的性质,我们该如何选择它的底层结构呢?是顺序表的数组还是链表呢?由此我们分析一下。

  • 如果是数组,很容易想到,完全符合对栈的性质的操作,如果是入栈,直接在数组最后一个位置插入即可,空间不够扩容就好,如果是出栈,直接将统计栈顶的变量减一即可,想要获取栈顶的数据,那不也很简单嘛。由此看来,数组还真是不错呢。

  • 如果是链表,入栈只要将数据头插即可,出栈就是头删,获取栈顶数据就是头节点的数据,这样看来,链表也挺不错呢。那么到底是选数组还是链表呢?

我们来看一下数据对比:
在这里插入图片描述

  • 可以看到,对于栈的性质,该表的前面五个特点都没有明显的优与劣,但是最后一个缓存利用率却能分出高下,很明显,实现一个栈,使用数组会更好。(对于什么是缓存利用率,这里就不讲解了,大家自行查找资料噢)

  • 选取了实现栈的底层结构,接下来就是对栈的初始化操作了。

  • 首先需要三个文件(与前面的单链表一样哈哈哈)stack.h,stack.c,test.cstack.h用来存放一些所需头文件,函数声明以及栈的结构体。stack.c用来实现函数接口,test.c用来测试。

  • 所需头文件:

#include <stdio.h>
// assert断言
#include <assert.h>
// 判空需用到
#include <stdbool.h>
// 动态空间需用
#include <stdlib.h>
  • 接下来就对控制栈的结构体进行创建:
typedef int STDataType;
typedef struct stack
{// 底层数组STDataType* a;// 容量int capacity;// 标识栈顶int top;
}stack;
  • 接下来是函数声明:
// 初始化
void STInit(stack* pt);
// 入栈
void STPush(stack* pt, STDataType x);
// 出栈
void STPop(stack* pt);
// 判空
bool STEmpty(stack* pt);
// 取栈顶元素
STDataType STTop(stack* pt);
// 栈的元素个数
int STSize(stack* pt);
// 销毁栈
void STDestroy(stack* pt);

怎么样,是不是看了函数接口就很简单呢,只有这些接口噢。

栈的初始化:

  • 对于栈的初始化,我们可以直接将topcapacity置为0,指向存放数据的数组的指针置为NULL。如下:
void STInit(stack* pt)
{// 这里断言一下pt是为了防止传递一个NULL指针,正确的应该传递一个结构体的地址assert(pt);pt->a = NULL;pt->capacity = 0;pt->top = 0;
}
  • 关于top实际上还可以初始化为-1。但-10实际差别不大,只是获取栈顶元素,判空和数据入栈这些代码会有所不同。如果top初始化为-1,那么top就是栈顶元素,如果top初始化为0top就是栈顶元素的下一个位置。所以我们在实现的时候,要注意这个top

  • 而本章采用的top0,也就是top是栈顶元素的下一个位置。

  • top = 0 ,实际上也间接体现了此时栈的数据个数。


栈顶入栈

  • 栈顶入栈就是在数组的最后一个位置添加一个数据即可,操作简单,不过这里要考虑一个扩容的问题。

  • 如果此时空间容量不够(判断条件:top == capacity),就需要扩容,这里使用realloc扩容,如果开始没有空间,该函数的功能就跟malloc一样。

  • 插入只要在top位置插入即可,最后top要加加一下噢。

下面是相关函数接口的代码实现:

void STPush(stack* pt, STDataType x)
{// 防止传递一个NULLassert(pt);// 检查容量看是否已满,满了就需要扩容if (pt->top == pt->capacity){int newcapacity = pt->capacity == 0 ? 4 : pt->capacity * 2;STDataType* tmp = realloc(pt->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}pt->a = tmp;pt->capacity = newcapacity;}// 在top位置放新的的数据,同时top要加一pt->a[pt->top++] = x;
}

栈顶出栈

  • 栈顶出栈就是抹去数组最后一个数据,只要top自减一即可。

  • 注意,当栈为空的时候,就不能出栈了,如何判断是否为空?在下面呢,别急哈哈哈。

下面是相关函数接口的代码实现:

void STPop(stack* pt)
{// 如果为空就不能删了。判空在后面写到。assert(pt && !STEmpty(pt));// top减一即可pt->top--;
}

栈体判空

  • 栈体判空,只需要判断一下top是否为0即可。如果是0,说明此时栈为空,返回true;如果不等于0,说明此时栈不为空,返回false

下面是相关函数接口的代码实现:

bool STEmpty(stack* pt)
{assert(pt);return pt->top == 0;
}

栈的数据个数

  • 前面说了,top就相当于是数据的个数,所以这里直接返回top的值即可。

下面是相关函数接口的代码实现:

int STSize(stack* pt)
{assert(pt);return pt->top;
}

获取栈顶元素

  • 由于top是最后一个元素的下一个位置,因此获取栈顶元素时,它的位置为top - 1

下面是相关函数接口的代码实现:

STDataType STTop(stack* pt)
{assert(pt && !STEmpty(pt));return pt->a[pt->top - 1];
}

栈的销毁

  • 有空间的开辟,那就要有空间的释放,这里称为销毁。

  • 销毁也很简单,只需要将指向栈空间的那个指针free即可。

  • 当然,最后可以将top置为0capacity也置为0

下面是相关函数接口的代码实现:

void STDestroy(stack* pt)
{assert(pt);free(pt->a);pt->capacity = 0;pt->top = 0;
}

整体代码

stack.h

#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>typedef int STDataType;
typedef struct stack
{STDataType* a;int capacity;int top;
}stack;// 初始化
void STInit(stack* pt);
// 入栈
void STPush(stack* pt, STDataType x);
// 出栈
void STPop(stack* pt);
// 判空
bool STEmpty(stack* pt);
// 取栈顶元素
STDataType STTop(stack* pt);
// 栈的元素个数
int STSize(stack* pt);
// 销毁栈
void STDestroy(stack* pt);

stack.c

#include "stack.h"void STInit(stack* pt)
{assert(pt);pt->a = NULL;pt->capacity = 0;pt->top = 0;
}void STPush(stack* pt, STDataType x)
{assert(pt);if (pt->top == pt->capacity){int newcapacity = pt->capacity == 0 ? 4 : pt->capacity * 2;STDataType* tmp = realloc(pt->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}pt->a = tmp;pt->capacity = newcapacity;}pt->a[pt->top++] = x;
}
void STPop(stack* pt)
{assert(pt && !STEmpty(pt));pt->top--;
}bool STEmpty(stack* pt)
{assert(pt);return pt->top == 0;
}
STDataType STTop(stack* pt)
{assert(pt && !STEmpty(pt));return pt->a[pt->top - 1];
}int STSize(stack* pt)
{assert(pt);return pt->top;
}void STDestroy(stack* pt)
{assert(pt);free(pt->a);pt->capacity = 0;pt->top = 0;
}

test.c

#include "stack.h"void test()
{stack st;STInit(&st);STPush(&st, 1);STPush(&st, 2);STPush(&st, 3);STPush(&st, 4);STPush(&st, 5);while (!STEmpty(&st)){printf("%d ", STTop(&st));STPop(&st);}printf("\n");STPush(&st, 5);STPush(&st, 55);STPush(&st, 555);STPush(&st, 5555);STPush(&st, 55555);STPush(&st, 555555);printf("%d\n", STTop(&st));while (!STEmpty(&st)){printf("%d ", STTop(&st));STPop(&st);}printf("\n");STDestroy(&st);
}int main()
{test();return 0;
}

😼写在最后

💝到这里,一个简简单单的栈就完成了,是不是很简单呢?不过也别得意哈,后面难的数据结构还没来呢,栈就是让你处于一个平静期,为后来的难度做准备呢哈哈哈哈哈。
❤️‍🔥后续将会持续输出有关数据结构的文章,你们的支持就是我写作的最大动力!

感谢阅读本小白的博客,错误的地方请严厉指出噢~

相关文章:

【数据结构】栈

文章目录&#x1f63a;前言栈初始化栈顶入栈栈顶出栈栈体判空栈的数据个数获取栈顶元素栈的销毁整体代码&#x1f63c;写在最后&#x1f63a;前言 &#x1f47b;前面我们学习了链表&#xff0c;总算是跨过一个台阶了&#xff0c;本章带大家轻松一波&#xff0c;领悟一下栈的魅力…...

C++单继承和多继承

C单继承和多继承继承单继承写法继承中构造函数的写法写法构造和析构的顺序问题多继承继承 1.继承&#xff0c;主要是遗传学中的继承概念 2.继承的写法&#xff0c;继承中的权限问题 3.继承中的构造函数的写法 继承&#xff1a;子类没有新的属性&#xff0c;或者行为的产生 父类…...

金三银四,今年企业招聘如何?

又是一年求职季&#xff0c;互联网人找工作&#xff0c;和找对象一样严谨&#xff0c;不随便放手更不随便牵手。于是挑挑拣拣&#xff0c;最后的结果可能就是把自己挑剩下了。 时间已经悄然滑进3月中旬&#xff0c;多少无处安放的青春&#xff0c;还没尘埃落定&#xff1f;优秀…...

数字信号处理:滤波、频谱

一、滤波算法 应该说数字滤波器可以有效减小50Hz工频的干扰&#xff0c;完全消除是不可能的。以20ms为最小单位的整倍数周期滤波&#xff0c;可以有效减少工频的干扰。 软件中构建 IIR 陷波或者 FIR 带阻 数字滤波器&#xff0c;消除工频干扰对测量结果的影响。 1. 自适应滤波 …...

C#等高级语言运行过程

C#等高级语言运行流程&#xff1a;假设您编写了一个 C# 程序并将其保存在一个称为源代码的文件中。特定于语言的编译器将源代码编译成 MSIL&#xff08;Microsoft 中间语言&#xff09;&#xff0c;也称为 CIL&#xff08;通用中间语言&#xff09;或 IL&#xff08;中间语言&a…...

如何优雅的用POI导入Excel文件

在企业级项目开发中&#xff0c;要经常涉及excel文件和程序之间导入导出的业务要求&#xff0c;那么今天来讲一讲excel文件导入的实现。java实现对excel的操作有很多种方式&#xff0c;例如EasyExcel等&#xff0c;今天我们使用的是POI技术实现excel文件的导入。POI技术简介1.P…...

【AI 工具】文心一言内测记录

文章目录一、申请内测二、收到内测邀请三、激活内测四、开始使用1、普通对话2、生成图片3、生成代码4、写剧本5、生成小说五、问题反馈一、申请内测 到 https://yiyan.baidu.com/welcome 页面 , 点击 " 开始体验 " 按钮 , 申请试用 ; 申请时 , 需要填写相关信息 ; 主…...

Github的使用

Github Date: March 8, 2023 Sum: Github的使用 Github 了解开源相关的概念 1. 什么是开源 2. 什么是开源许可协议 开源并不意味着完全没有限制&#xff0c;为了限制使用者的使用范围和保护作者的权利&#xff0c;每个开源项目都应该遵守开源许可协议&#xff08; Open Sou…...

抽丝剥茧还原真相,记一次神奇的崩溃

作者&#xff1a;靳倡荣 本文详细回放了一个崩溃案例的分析过程。回顾了C多态和类内存布局、pc指针与芯片异常处理、内存屏障的相关知识。 一、不讲“武德”的崩溃 1.1 查看崩溃调用栈 客户反馈了一个崩溃问题&#xff0c;并提供了core dump文件&#xff0c;查看崩溃调用栈如下…...

学习笔记八:docker资源配额

docker容器控制cpudocker容器控制cpu指定docker容器可以使用的cpu份额两个容器A、B的cpu份额分别为1000和500&#xff0c;结果会怎么样&#xff1f;给容器实例分配512权重的cpu使用份额总结CPU core核心控制扩展&#xff1a;服务器架构CPU配额控制参数的混合使用cpuset-cpus和c…...

小米10s格机修复 nv报错案例解析 关于基带分区的一些常识

前面分享过几期关于基带 diag端口与qcn相关的几篇帖子。其中一位粉丝朋友联系我。他的机型因为误格机导致手机进不去系统&#xff0c;反复进入官方rec报错nv损坏。进不去系统。 有兴趣的朋友可以参阅我的几个帖子&#xff0c;只是个人的一些片面理解。 基带相关贴; 安卓玩机…...

【3.17】MySQL索引整理、回溯(分割、子集问题)

3.1 索引常见面试题 索引的分类 什么是索引&#xff1f; 索引是一种数据结构&#xff0c;可以帮助MySQL快速定位到表中的数据。使用索引&#xff0c;可以大大提高查询的性能。 按「数据结构」分类&#xff1a;Btree索引、Hash索引、Full-text索引。 InnoDB 存储引擎创建的聚簇…...

转解疑难杂症,详解vector迭代器失效和深浅拷贝的问题

前文http://t.csdn.cn/kVeVX——vector模拟实现本篇文章主要是针对vector中的两个比较经典的问题同时也是上一篇文章遗留下来的问题进行详细解释&#xff0c;第一个就是迭代器失效的问题&#xff0c;第二个是深浅拷贝的问题。ps&#xff1a;注意本文演示用的代码是上一篇vector…...

质量工具之头脑风暴法

云质QMS原创 转载请注明来源 作者&#xff1a;王洪石 1. 什么是头脑风暴法 头脑风暴最早是精神病理学上的用语&#xff0c;指的是精神病患者的精神错乱状态&#xff0c;后来拓展为无限制的自由联想和讨论&#xff0c;其目的在于产生新创意、激发新设想&#xff0c;或通过找到新…...

【3】核心易中期刊推荐——人工智能计算机仿真

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…...

vFlash软件简介

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…...

mysql-online-ddl是否需要rebuild

一、背景 DDL一直是DBA业务中的大项&#xff0c;看了TIDB的DDL讲解&#xff0c;恰巧我们的mysql业务大表也遇到了DDL的变更项&#xff0c;变更内容是将varchar(10)变更成varchar(20),这个变更通过官方文档很容易知道是不需要rebuild的&#xff08;这里要注意下这个varchar(255…...

力扣-超过经理收入的员工

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;181. 超过经理收入的员工二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其…...

决策树基础知识点解读

目录 ID3算法 C4.5算法 CART树 ID3算法 定义:在决策树各个结点上应用信息增益准则选择特征&#xff0c;递归的构建决策树。该决策树是多分支分类。 信息增益 意义&#xff1a;给定特征X的条件下&#xff0c;使得类别Y的信息的不确定性减少的程度。取值越大越好。 定义&am…...

【C++】入门知识之 命名空间与输入输出

前言C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; 20世纪80年代&#xff0c; 计算机界提出了OOP(object oriented …...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...