一文了解栈
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、栈是什么?
- 二、栈的实现思路
- 1.顺序表实现
- 2.单链表实现
- 3.双向链表实现
- 三、接口函数的实现
- 1.栈的定义
- 2.栈的初始化
- 3.栈的销毁
- 4.入栈
- 5.出栈
- 6.返回栈顶元素
- 7.判空
- 8.返回栈中数据个数
- 四、文件总览
- 1.头文件
- 2.功能函数
- 3.测试文件
- 总结

前言
栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。在数据结构中,栈是比较简单的一种结构。
一、栈是什么?
堆栈又名栈(stack),它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。


二、栈的实现思路
1.顺序表实现
代码如下(示例):
typedef struct StackList
{STDataType* a; //指向动态开辟的空间int top; //栈顶所在下标的下一位(也可以指向栈顶)int capacity;//栈容量
}ST;

2.单链表实现
代码如下(示例):
typedef struct StackNode
{STDataType x;//数据StackNode* next;//指针域,指向下一结点
}ST;
struct Stack
{ST* phead;//指向第一个结点ST* ptail;//指向尾结点
}

3.双向链表实现
typedef struct StackNode
{STDataType x;//数据StackNode* next;//指向下一结点StackNode* prev;//指向上一结点
}ST;
struct Stack
{ST* phead;//指向第一个结点ST* ptail;//指向尾结点
}

在这里我们推荐采用顺序表来实现对栈的操作,原因如下:
- 栈的特性利用了顺序表尾插尾删效率高的特性,虽然有时需要扩容,但是链表创建结点也同样需要成本,而顺序表扩容频率不像链表一样如此频繁。链表频繁开辟节点也是很耗时的。
- 我们知道CPU与主存速度上存在巨大差距,为了提高效率,CPU和主存之间还存在着高速缓存。 CPU访问缓存的速度是快于主存。每次CPU取数据时会访问缓存看看存不存在所需的数据,如果不存在才会访问主存,然后将数据所在的内存块加载到缓存中。由于顺序表空间是连续的,根据缓存的空间局部性原理,采用顺序表命中率会高于链表,所以效率高。
三、接口函数的实现
1.栈的定义
typedef int STDataType;
typedef struct Stack
{STDataType* a;//动态开辟内存int top;//栈顶的下一位int capacity;栈的容量
}ST;
这里top定义为栈顶下一位是为了下面下表访问方便,也可以定义为指向栈顶的top可以根据个人需要决定。
2.栈的初始化
void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;pst->top = 0;
}
初始化时,空间a先置空指针,capacity和top置零,这是栈没有数据,top指向0,也确实是栈顶的下一位。
3.栈的销毁
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->capacity = pst->top = 0;
}
先对pst进行assert断言,再对开辟的空间进行释放,将指针置零,capacity和top置零即可。
4.入栈
void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top){int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;STDataType*tmp=(STDataType*)realloc(pst->a, newcapacity*sizeof(STDataType));if (tmp == NULL){perror("realloc");return;}pst->a = tmp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}
入栈需要注意的点是判断是否容量够用,当capacity和top相等时存满,需要扩充。在扩充时需要判断原容量是不是0,这里进行一个三目操作符判断。之后就是realloc扩容,最后将相应的capacity和top修改就行。
5.出栈
void STPop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}
出栈时应判断栈是否为空,所以这里除了判断pst的有效性,还要判断top的位置。最后让top向前移一位就进行了出栈。
6.返回栈顶元素
STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top-1];
}
判断pst有效性和栈是否为空,再将栈顶的元素返回即可。
7.判空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}
这里需要返回bool类型,需要加<stdbool.h>头文件。当top为零时栈为空,返回true,否则返回false。
8.返回栈中数据个数
int STSize(ST* pst)
{assert(pst);return pst->top;
}
这里因为我们的top指向栈顶数据的下一位,所以top即为数据个数。返回即可。
四、文件总览
1.头文件
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;// 初始化和销毁
void STInit(ST* pst);
void STDestroy(ST* pst);// 入栈 出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);// 取栈顶数据
STDataType STTop(ST* pst);// 判空
bool STEmpty(ST* pst);
// 获取数据个数
int STSize(ST* pst);
2.功能函数
#include"Stack.h"void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;pst->top = 0;
}void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->capacity = pst->top = 0;
}void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top){int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;STDataType*tmp=(STDataType*)realloc(pst->a, newcapacity*sizeof(STDataType));if (tmp == NULL){perror("realloc");return;}pst->a = tmp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}void STPop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top-1];
}bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}int STSize(ST* pst)
{assert(pst);return pst->top;
}
3.测试文件
int main()
{// 入栈:1 2 3 4// 出栈:4 3 2 1 / 2 4 3 1ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);printf("%d ", STTop(&s));STPop(&s);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d ", STTop(&s));STPop(&s);}STDestroy(&s);
}

总结
这就是本期文章的全部内容,期待你的一键三连和评论。
相关文章:
一文了解栈
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、栈是什么?二、栈的实现思路1.顺序表实现2.单链表实现3.双向链表实现 三、接口函数的实现1.栈的定义2.栈的初始化3.栈的销毁4.入栈5.出栈6.返回栈…...
C语言----汉诺塔问题
1.什么是汉诺塔问题 简单来说,就是有三个柱子,分别为A柱,B柱,C柱。其中A柱从上往下存放着从小到大的圆盘,我们需要借助B柱和C柱,将A柱上的所有圆盘转移到C柱上,并且一次只能移动一个圆盘&#…...
Python中驼峰命名法和下划线命名法相互转换的实战代码
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
【hackmyvm】vivifytech靶机
渗透思路 信息收集端口扫描端口服务信息目录扫描爆破hydra--sshgit提权 信息收集 ┌──(kali㉿kali)-[~] └─$ fping -ag 192.168.9.0/24 2>/dev/null 192.168.9.119 --主机 192.168.9.164 --靶机个人习惯,也方便后续操作,将IP地址赋值给一个变…...
纯血鸿蒙APP实战开发——手写绘制及保存图片
介绍 本示例使用drawing库的Pen和Path结合NodeContainer组件实现手写绘制功能。手写板上完成绘制后,通过调用image库的packToFile和packing接口将手写板的绘制内容保存为图片,并将图片文件保存在应用沙箱路径中。 效果图预览 使用说明 在虚线区域手写…...
在什么情况下表单会被重复提交?如何避免?
表单被重复提交是Web应用中常见的问题,通常在用户提交表单后点击按钮多次,或在表单提交后刷新页面时发生。这可能导致数据的重复处理,比如重复记录或订单。 何时会发生表单重复提交? 用户多次点击提交按钮:在网络延迟…...
JavaScript 中的 Class 类
🔥 个人主页:空白诗 文章目录 🔥 引言🎯 基础知识🏗️ 构造函数 (Constructor)🔐 私有字段 (Private Fields)🔐 私有方法 (Private Methods)🧬 继承 (Inheritance)📦 静态…...
python实验三 实现UDP协议、TCP协议进行服务器端与客户端的交互
实验三 实验题目 1、请利用生成器构造一下求阶乘的函数Factorial(),定义一个函数m(),在m()中调用生成器Factorial()生成小于100的阶乘序列存入集合s中,输出s。 【代码】 def factorial():n1f1while 1: f * n yield (f) n1…...
ServiceNow 研究:通过RAG减少结构化输出中的幻觉
论文地址:https://arxiv.org/pdf/2404.08189 原文地址:rag-hallucination-structure-research-by-servicenow 在灾难性遗忘和模型漂移中,幻觉仍然是一个挑战。 2024 年 4 月 18 日 灾难性遗忘: 这是在序列学习或连续学习环境中出现…...
ADS基础教程10-多态性(动态模型选择)
目录 一、多态性定义二、操作步骤1.模型建立2.模型选择3.执行仿真 一、多态性定义 ADS中支持一个Symbol中,可以同时存在多个子图。在仿真时可以动态选择不同的子图继续宁仿真。 二、操作步骤 1.模型建立 在上一章A…...
代码随想录第四十六天|单词拆分
题目链接:. - 力扣(LeetCode)...
RabbitMQ的介绍和使用
1.同步通讯和异步通讯 举个例子,同步通讯就像是在打电话,因此它时效性较强,可以立即得到结果,但如果你正在和一个MM打电话,其他MM找你的话,你们之间是不能进行消息的传递和响应的 异步通讯就像是微信&#…...
前端get请求日期类型参数向后端传参失败
1、背景 get请求,通过url上传参,因此日期类型是string类型数据 2、异常信息 nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for…...
【docker 】 push 镜像提示:denied: requested access to the resource is denied
往 Docker Registry (私服)push 镜像提示:denied: requested access to the resource is denied 镜像push 语法:docker push <registry-host>:<registry-port>/<repository>:<tag> docker push 192.16…...
浏览器各类好用插件使用及常见问题(技巧)总结
目录 Vimium C快捷键问题为什么Vimium C - 全键盘操作浏览器插件在百度页面中, x ,o,f等快捷键不起作用如何使用viminum c插件进行自定义快捷键?vimucm 为什么在浏览器首页时快捷键不起作用? 网页截图问题firefox 网页截图使用 idm问题浏览器点击idm 不下载? 待续、更新中 V…...
Python批量计算多张遥感影像的NDVI
本文介绍基于Python中的gdal模块,批量基于大量多波段遥感影像文件,计算其每1景图像各自的NDVI数值,并将多景结果依次保存为栅格文件的方法。 如下图所示,现在有大量.tif格式的遥感影像文件,其中均含有红光波段与近红外…...
6.k8s中的secrets资源
一、Secret secrets资源,类似于configmap资源,只是secrets资源是用来传递重要的信息的; secret资源就是将value的值使用base64编译后传输,当pod引用secret后,k8s会自动将其base64的编码,反编译回正常的字符…...
git 更换远程仓库地址三种方法总结
git 更换远程仓库地址三种方法总结 一、前言 由于私服的 gitlab 的地址变更,导致部分项目代码提交不上去,需要修改远端仓地址。 其它需要修改远程仓地址的情况如:切换git clone 协议由ssh变为https。 二、环境 windows 10git version 2.3…...
快速找出存(不存在)在某个(或多个)文件的文件夹
首先,需要用到的这个工具: 度娘网盘 提取码:qwu2 蓝奏云 提取码:2r1z 想要找出有下面这个文件存在的文件夹 切换到批量文件复制版块,快捷键Ctrl5 右侧,搜索添加 选定范围,勾选搜索文件夹、包…...
Linux USB转串口设备路径的查找方法
1、USB转串口设备 USB转串口设备是在嵌入式软件开发过程中经常要使用的,常常用于对接各种各样的串口设备。如果一台linux主机上使用多个usb转串口设备时,应用程序中就需要知道自己操作的是哪个串口设备。串口设备在系统上电时,由于驱动加载的…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
