深入理解栈(Stack)(纯小白进)

news2024/10/12 6:12:36

目录:

  • 一、栈是什么?
    • 1. 栈的概念
    • 2.栈的结构选择
  • 二、栈的实现
    • 1. 栈结构体的定义
    • 2. 栈的初始化
    • 3. 栈的销毁
    • 4. 入栈
    • 5.出栈
    • 6. 取栈顶元素
    • 7. 栈中元素的个数
    • 8. 判断栈是否为空
  • 总结

一、栈是什么?

1. 栈的概念

栈(Stack):⼀种特殊的线性表,是一种常见的数据结构,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。栈的应用非常广泛,例如函数调用栈、表达式求值、括号匹配等。

栈的基本操作包括:

  1. 入栈(Push):将元素压入栈顶。

  2. 出栈(Pop):将栈顶元素弹出。

  3. 查看栈顶元素(Top):获取栈顶元素的值,但不弹出。

  4. 判断栈是否为空(Empty):检查栈是否为空。

  5. 查看栈的大小(Size):获取栈内元素的个数。

栈就像是一叠摞在一起的盘子,我们放盘子只能放到盘子的最上面,同理取盘子,也只能从栈的最上方来取。放盘子称为入栈,去盘子称为出栈。
【数据结构入门】栈(Stack)的实现(定义、销毁、入栈、出栈等) | 图解数据结构,超详细哦~_销毁栈-CSDN博客

2.栈的结构选择

栈底层结构选型:

栈的实现⼀般可以使⽤数组或者链表实现,相对⽽⾔数组的结构实现更优⼀些。因为数组在尾上插⼊数据的代价⽐较⼩。

对比:

数组实现的栈是一种固定大小的栈,其优点是实现简单,缺点是大小固定。

链表实现的栈是一种动态大小的栈,其优点是大小可变,缺点是实现稍微复杂。

img

img

定长的静态栈,实际中我们一般不使用,所以我们下面主要实现的就是支持动态增长的栈 。


二、栈的实现

1. 栈结构体的定义

基于下面这张图,再类比顺序表,我们可以发现,栈的实现需要三个元素。
在这里插入图片描述

typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;        //栈数组
	int capacity;           //栈的空间大小
	int top;                //栈顶位置
}ST;

对数据类型进行重命名,这样以后需要更换其他数据类型使用的时候只需要更改这一个地方就可以了。

ps: 定义一个数组动态的开辟空间,top用来记录栈顶元素的位置,capacity来表示栈的总容量大小。


2. 栈的初始化

先将栈中所有的数据都初始化为空,因为栈只需要在容量满的时候进行扩容,这里可以不需要先开辟空间,这一步可以节省。
具体的实现是:

//栈的初始化
void STInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

3. 栈的销毁

有初始化必然有销毁。

我们需要释放栈中的空间,别忘了将其置为NULL,防止内存泄漏。
释放掉栈中所有的元素。

注意:

这里不能直接对ps进行释放,因为ps中的arr是动态开辟来的,所以需要先对arr进行free,然后将其他成员置空。

//栈的销毁
void STDestroy(ST* ps)
{
	assert(ps);
	if(ps->arr)
	  free(ps->arr);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

4. 入栈

//数据入栈
void STPush(ST* ps, STDataType x); //STDataType x 是我们需要插入的数据

在这里插入图片描述

在入栈之前我们需要判断数组容量够不够,需不需要扩容。
在这里插入图片描述
在这里插入图片描述

具体实现是

void STPush(ST* ps, STDataType x) {
	assert(ps);
	if (ps->top == ps->capacity) {
		STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
		if (temp == NULL) {
			perror("realloc fail");
			return;
		}
		ps->a = temp;
		ps->capacity *= 2;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

5.出栈

注意,如果栈为空,则不能出数据。

//数据出栈
void STPop(ST* ps);
//栈判空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

在这里插入图片描述

开始出栈

//数据出栈
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

6. 取栈顶元素

//取栈顶元素
STDataType STTop(ST* ps);
//取栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->arr[ps->top - 1];
}

那么只要栈不为空,就可以一直取栈顶元素
在这里插入图片描述


7. 栈中元素的个数

//获取栈中有效元素个数
int STSize(ST* ps);
//获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

8. 判断栈是否为空

bool  STEmpty(ST* ps) {
	assert(ps);
	return ps->top == 0;
}

总结

栈是一种简单且高效的数据结构,适用于需要“后进先出”操作的场景。通过掌握栈的基本操作和实现方式,我们可以更好地理解和应用这一数据结构,从而提高程序的效率和可靠性。希望这篇博客可以帮租到你,下一站:队列。

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

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

相关文章

游戏开发指南:使用 UOS C# 云函数快速构建与部署服务端逻辑实战教学

零基础的服务端小白,现在也可以使用 Unity 结合 C# 来轻松搞定游戏服务端啦! 在本篇文章中,我们将以游戏中的“抽卡”功能为例,展示如何使用 Unity Online Services(UOS)提供的强大 C# 云函数服务&#xf…

Elasticsearch(二)集成Spring Boot 基本的API操作

目录 一、集成Spring Boot 1、创建项目 2、pom文件 查看springboot集成的依赖 3、增加es的config类 二、索引相关API 1、创建索引 2、获取索引,判断其是否存在 3、删除索引 三、文档相关API 1、添加文档 2、获取文档,判断是否存在 3、获取文档…

Java后端面试----某团一面

美团一面 1.介绍一下你的第一个项目 这个就不多说了,主要是根据自己的简历上面的项目进行一个简短的概括使用的技术栈和什么背景解决了什么问题等等。 2.线程安全的类有哪些,平时有使用过哪些,主要解决什么问题 在Java中线程安全的类比如…

对后端返回的日期属性进行格式化(扩展 Spring MVC 的消息转换器)

格式化之前 格式化之后: 解决方式 方式一 在属性中加上注解,对日期进行格式化 JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//JsonFormat(pattern &quo…

echarts按需引入解决项目大小问题

背景: 按需加载缩减项目大小,提升项目性能和可用性 实现: 创建echarts.js main.js进行配置 页面中引用 效果 全量导入 按需加载:

Chrome清除nslookup解析记录 - 强制http访问 - 如何禁止chrome 强制跳转https

步骤: 地址栏输入 chrome://net-internals/#hsts在Delete domain 栏的输入框中输入要http访问的域名,然后点击“delete”按钮最后在Query domain 栏中搜索刚才输入的域名,点击“query”按钮后如果提示“Not found”即可! 办法来自…

Linux系统:apt upgrade与apt update 命令的作用

一.sudo apt update命令 sudo apt update命令的主要作用是更新本地软件包列表。‌ 它不会下载或安装新的软件包,而是更新本地系统中软件包的列表,以反映远程存储库中的最新可用软件包信息。这确保了软件包管理器(APT)具有最新的软…

第十六周周报:单发的目标检测系列

目录 摘要 Abstract 一、SSD 1.1 模型结构 1.2 代码 二、YOLO 三、Termius 总结 摘要 本周主要学习单阶段的目标检测算法,如SSD、YOLO模型。详细学习了每个模型的原理,以及SSD和YOLO模型之间的异同。在本篇博客中将展示SSD的PyTorch实现代码&am…

Django使用uwsgi和nginx进行手动部署

在Django项目中使用uWSGI和Nginx进行部署是一种常见的生产环境配置。以下是一个详细的步骤指南,帮助你完成这个过程。 前提条件 有一个已经开发好的Django项目。服务器已安装Python、pip、Nginx和uWSGI。有一个有效的域名(可选,但推荐)。 步骤一&#xf…

CPU指令融合技术概述

什么是指令融合? 某些指令,例如add $3,$2,0, 只会使用rd/rs两个字段,但是这条指令却占用了全部32个bit, 这样会使得代码密度不高,指令域的有效利用率不高;这样,在实现某些功能的情况下,会使得CP…

Java创建线程池和线程池的七个核心参数

线程池的工作流程是:当一个任务被提交到线程池时,线程池会根据当前的线程数量和工作队列的状态来决定如何处理这个任务。如果当前运行的线程数量小于corePoolSize,则创建新线程执行任务;如果大于等于corePoolSize,则将…

毕设开源 大数据电影数据分析与可视化系统(源码+论文)

文章目录 0 前言1 项目运行效果2 设计概要3 最后 0 前言 🔥这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师…

完全免费安卓远程安卓方案:FRP+ADB甲壳虫方案,远程手机不是问题。

引言 在当今这个数字化时代,无论是在个人项目还是商业应用中,能够从公网访问到内网设备的能力变得越来越重要,尤其是安卓终端设备,在必要的情况下,从安卓远程到安卓进行紧急指导救援是未来一种重要的趋势. 通过合理的…

Java - WebSocket

一、WebSocket 1.1、WebSocket概念 WebSocket是一种协议,用于在Web应用程序和服务器之间建立实时、双向的通信连接。它通过一个单一的TCP连接提供了持久化连接,这使得Web应用程序可以更加实时地传递数据。WebSocket协议最初由W3C开发,并于2…

3种常用的缓存读写策略详解

在详解3种常用的缓存读写之前,我们先要了解什么事缓存读写。 缓存读写是指在使用缓存技术时,对数据进行读取和更新的操作过程。缓存是一种用于提高系统性能和可扩展性的技术,通过减少对慢速存储(如数据库)的访问次数&…

CAN总线仲裁机制

文章目录 1、什么是CAN总线仲裁?2、仲裁机制3、仲裁过程 1、什么是CAN总线仲裁? CAN总线上的每个节点都能监测到总线上发送的数据,当总线空闲时每个节点都能够进行报文发送,多个节点同时发送报文时,最终由哪个节点来进…

中间件有哪些分类?

中间件的分类 中间件是位于操作系统和应用程序之间的软件,它提供了一系列服务来简化分布式系统中的应用程序开发和集成。中间件可以根据其功能和用途被分为不同的类别。以下是中间件的一些主要分类: 1. 通信处理(消息)中间件&am…

Sentinel 1.80(CVE-2021-44139)

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性 Report a Sentinel Security Vulnerability …

华为eNSP实验:以太网交换---MAC地址漂移防止与检测

一:MAC地址漂移 MAC地址漂移是一种网络攻击技术,它利用了网络设备(如交换机)的动态学习特性来改变网络流量的路径。这种攻击可能导致数据包被错误地转发到未经授权的设备上,从而造成信息泄露或拒绝服务攻击。为了防止…

ViirtualBox+Vagrant快速创建虚拟机,固定IP地址

ViirtualBoxVagrant配置虚拟机共分三步 1.ViirtualBox的安装 2.Vagrant的安装 3.VirtualBoxVagrant配置虚拟机 1.安装virtual Box 2.进入官网 下载 https://www.virtualbox.org/wiki/Downloads 下载对应版本 https://www.virtualbox.org/wiki/Download_Old_Builds_6_1 使用…