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

栈 之 如何实现一个栈

前言

栈最鲜明的特点就是后进先出,一碟盘子就是类似这样的结构,最晚放上去的,可以最先拿出来。本文将介绍的是如何自己实现一个栈结构。

栈的操作

栈是一种先进后出(Last-In-First-Out, LIFO)的数据结构,常见操作包括:

1、入栈(Push):将元素压入栈顶。
2、出栈(Pop):弹出栈顶元素并返回其值。
3、查看栈顶元素(Peek):返回栈顶元素的值,但不对栈进行修改。
4、判断栈是否为空(isEmpty):检查栈是否为空,如果栈中没有任何元素,则返回 true;否则返回 false。
5、获取栈的大小(size):返回栈中元素的数量。
6、清空栈(clear):清除栈中的所有元素,使其变为空栈。
这些是栈的基本操作。栈的实际使用还可能涉及其他操作,如遍历栈、搜索特定元素、栈的深度等等。根据具体的需求,你可以针对栈的特性来自定义其他更复杂的操作。

栈的实现

栈是较容易实现的抽象数据结构之一。我们可以选择数组或者链表来实现,它们各有特点,前者容量有限且固定,但操作简单,而后者容量理论上不受限,但是操作并不如数组方便,每次入栈要进行内存申请,出栈要释放内存,稍有不慎便造成内存泄露。本文对两种实现都做介绍。

1、用数组实现栈

数组之你值得了解的底层

/*** 用数组实现一个栈*/
public class MyStack {private int maxSize;  //栈的大小private int[] stackArray; // 数组,模拟一个栈,用于存放private int top = -1; // 表示栈顶,初始为-1public MyStack(int maxSize) {this.maxSize = maxSize;stackArray = new int[this.maxSize];}public void push(int value) {//判断是否栈满if(isFull()){System.out.println("栈满了..");return;}stackArray[++top] = value;}//弹出栈顶的元素并返回public int pop(int value) {//判断栈是否为空if(isEmpty()) {throw new RuntimeException("栈空,没有数据~~");}value = stackArray[top--];return value;}//查看栈顶的元素public int peek() {//判断栈是否为空if(isEmpty()) {throw new RuntimeException("栈空,没有数据~~");}return stackArray[top];}// 显示栈中的数据-从栈顶开始显示public void list() {// 判断是否栈空if (isEmpty()) {System.out.println("栈空~~");return;}//从栈顶开始展示数据for (int i = top; i >= 0; i--) {System.out.printf("stack[%d]=%d\n", i, stackArray[i]);}}//栈空public boolean isEmpty() {return top == -1;}//栈满public boolean isFull() {return top == (maxSize - 1);}
}

2、用队列实现栈

Java两个队列实现一个栈

3、用链表实现栈

/*** @Description* @Author Flag* @Date: 2021/7/20 8:53* @Version: 1.0**/
public class LinkedStackDome {public static void main(String[] args) {//测试一下LinkedStack是否正常//先创建一个ArrayStack对象->表示栈LinkedStack stack = new LinkedStack(4);String key = "";boolean loop = true;//用于控制是否退出Scanner scanner = new Scanner(System.in);while (loop){System.out.println("show:表示显示栈");System.out.println("exit:退出程序");System.out.println("push:表示添加元素到栈(入栈)");System.out.println("pop:表示从栈取出数据(出战)");System.out.println("请输入你的选择:");key = scanner.next();switch (key){case "show":stack.show();break;case "exit":scanner.close();loop = false;break;case "push":System.out.println("请输入一个数字");int i = scanner.nextInt();stack.push(i);break;case "pop":try{int pop = stack.pop();System.out.println("出栈的数据:"+pop);} catch (Exception e){System.out.println(e.getMessage());}break;default:break;}}}}class LinkedStack{//定义栈的大小private int maxSize;//链表模拟栈,private LinkedStackNode first;//top表示栈顶,初始化是-1private int top;/*** 构造方法* @param maxSize 栈的大小*/public LinkedStack(int maxSize) {this.maxSize = maxSize;top = -1;}/*** 判断栈是否满了* @return*/public boolean isFull(){return top+1 == maxSize;}/*** 入栈* @param value 入栈的元素*/public void push(int value){//1、判断栈是否满了if(this.isFull()){System.out.println("栈已经满了,不能再添加元素");return;}//2、新创建一个节点,用于添加到链表上LinkedStackNode node = new LinkedStackNode(value);//3、将top++,表示链表中的元素新增了一个top++;//4、判断头元素是否为null,如果是null,代表是第一个元素,则直接让新元素当第一个元素if(first == null){first = node;return;}//5.如果头元素不是null,则证明,此时链表中已经有元素,则将新元素添加上即可//5.1获取到链表的尾部LinkedStackNode middleNode = first;while (middleNode.getNext() != null){middleNode = middleNode.getNext();}//5.2将链表添加上去middleNode.setNext(node);}/*** 出栈* @return 出栈的元素*/public int pop(){//1.判断栈是否为nullif(this.isEmpty()){throw new RuntimeException("栈中没有元素");}//2.将链表的数量减一top -- ;//3.如果链表中是否只有一个元素if(first.getNext() == null){LinkedStackNode popNode = this.first;this.first = null;return popNode.getNumber();}//4.如果链表中有不只一个元素//4.1.定义一个中间变量,让他指向链表的最后一个元素,即最后要出栈的元素LinkedStackNode lastNode = first;//4.2.定义一个中间变量,用来用来获取到比lastNode前一个元素,‘//因为是单向链表,我们出栈后,要置空指向最后一个元素的指针,所以需要找到最有一个元素的前一个元素进行操作LinkedStackNode beforeLastNode = null;//4.2.遍历链表,直到lastNode是最后一个元素,此时,如果链表中只有一个元素,则while (lastNode.getNext() != null){//将lastNode给到beforeLastNode//然后lastNode向后移动//此时就构造出 beforeLastNode在lastNode前一个位置的情况beforeLastNode = lastNode;lastNode = lastNode.getNext();}//4.3.此时将最后一个元素的前一个元素的next指针变成null,则相当于舍弃掉了最后一个元素beforeLastNode.setNext(null);//4.3.返回lastNode的编号return lastNode.getNumber();}/*** 显示栈的元素*/public void show(){//判断栈是否为nullif(this.isEmpty()){System.out.println("栈中无元素");return;}//定义一个新的链表节点LinkedStackNode newLinedStackHead = null;//正向遍历原始链表,将链表的每一个元素,都放到新的链表的第一个元素//因为前面做了判断,所以first不可以为nullLinkedStackNode oldLinkedStackNode = first;//直到原始链表元素为null时,结束while (oldLinkedStackNode != null){LinkedStackNode middleNode = new LinkedStackNode(oldLinkedStackNode.getNumber());if(newLinedStackHead == null){newLinedStackHead = middleNode;} else {middleNode.setNext(newLinedStackHead);newLinedStackHead = middleNode;}//移动原始链表的位置oldLinkedStackNode = oldLinkedStackNode.getNext();}while (newLinedStackHead != null){System.out.println(newLinedStackHead.getNumber());newLinedStackHead = newLinedStackHead.getNext();}}/*** 判断栈是否为null* @return 结果*/public boolean isEmpty(){return top == -1;}
}/*** 链表栈的节点*/
class LinkedStackNode{private int number;private LinkedStackNode next;public LinkedStackNode(int number) {this.number = number;}public int getNumber() {return number;}public LinkedStackNode getNext() {return next;}public void setNext(LinkedStackNode next) {this.next = next;}
}

栈的应用

1、栈的应用——递归

1)、递归的定义

递归是一种重要的程序设计方法。简单地说,若在一个函数、过程或数据结构的定义中又应用了它自身,则这个函数、过程或数据结构称为是递归定义的,简称递归。
它通常把一个大型的复杂问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的代码就可以描述岀解题过程所需要的多次重复计算,大大减少了程序的代码量但在通常情况下,它的效率并不是太高。

2)、斐波那契数列

2、栈的应用——四则运算表达式求值

1)、后缀表达式计算结果
2)、中缀表达式转后缀表达式

笔记

相关文章:

栈 之 如何实现一个栈

前言 栈最鲜明的特点就是后进先出,一碟盘子就是类似这样的结构,最晚放上去的,可以最先拿出来。本文将介绍的是如何自己实现一个栈结构。 栈的操作 栈是一种先进后出(Last-In-First-Out, LIFO)的数据结构&#xff0c…...

uni-app:自带的消息提示被遮挡的解决办法(自定义消息提示框)

效果&#xff1a; 代码&#xff1a; 1、在最外层或者根组件的模板中添加一个容器元素&#xff0c;用于显示提示消息。例如&#xff1a; <div class"toast-container" v-if"toastMessage"><div class"toast-content">{{ toastMessa…...

PHP设备检验系统Dreamweaver开发mysql数据库web结构php编程计算机网页代码

一、源码特点 PHP设备检验系统是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 下载地址 https://download.csdn.net/download/qq_41221322/88306259 php设备检验系统1 …...

Windows 可以使用以下快捷键打开终端(命令提示符)

Windows 可以使用以下快捷键打开终端&#xff08;命令提示符&#xff09; 使用快捷键 Win R 打开 “运行” 对话框&#xff0c;然后输入 “cmd” 并按下 Enter 键。这将打开默认的命令提示符窗口。 使用快捷键 Ctrl Shift Esc 打开任务管理器&#xff0c;然后在 “文件” …...

Netty编程面试题

1.Netty 是什么&#xff1f; Netty是 一个异步事件驱动的网络应用程序框架&#xff0c;用于快速开发可维护的高性能协议服务器和客户端。Netty是基于nio的&#xff0c;它封装了jdk的nio&#xff0c;让我们使用起来更加方法灵活。 2.Netty 的特点是什么&#xff1f; 高并发&a…...

math_review

topics mathmatics supreme and optimumNorm and Linear producttopology of R*Continuious Function supreme and optimum Def 1: 非空有界集合必有上确界 common norm (1) x ∈ \in ∈ Rn, ||x||2 x 1 2 x 2 2 . . . x n 2 \sqrt {x_1^2x_2^2...x_n^2} x12​x22​.…...

肖sir__设计测试用例方法之场景法04_(黑盒测试)

设计测试用例方法之场景法 1、场景法主要是针对测试场景类型的&#xff0c;顾也称场景流程分析法。 2、流程分析是将软件系统的某个流程看成路径&#xff0c;用路径分析的方法来设计测试用例。根据流程的顺序依次进行组合&#xff0c;使得流程的各个分支能走到。 举例说明&…...

plt函数显示图片 在图片上画边界框 边界框坐标转换

一.读取图片并显示图片 %matplotlib inline import torch from d2l import torch as d2l读取图片 image_path ../data/images/cat_dog_new.jpg # 创建画板 figure d2l.set_figsize() image d2l.plt.imread(image_path) d2l.plt.imshow(image);二.给出一个(x左上角,y左上角,…...

运行期获得文件名和行号

探索动态日志模块的实现 最初的目标是创建一个通用的日志模块, 它具有基本的日志输出功能并支持重定向. 这样, 如果需要更换日志模块, 可以轻松实现. 最初的构想是通过函数重定向, 即使用 dlsym 来重定向所有函数以实现打印功能. 然而, 这种方法引发了一个问题, 即无法正确获…...

数组操作UNIAPP

字符串转数组 let string "12345,56789" string.split(,) // [12345,56789] 数组转字符串 let array ["123","456"] array.join(",") // "123,456" 数组元素删除 let array [123,456] // 删除起始下标为1&#xff0…...

MySQL——无法打开MySQL8.0软件安装包或者安装过程中失败,如何解决?

在运行MySQL8.0软件安装包之前&#xff0c;用户需要确保系统中已经安装了.Net Framework相关软件&#xff0c;如果缺少此软件&#xff0c;将不能正常地安装MySQL8.0软件。 解决方案&#xff1a;到这个地址 https://www.microsoft.com/en-us/download/details.aspx?id42642…...

DB2存储过程如何编写和执行

db2执行文件参数&#xff1a; -t 表示语句使用默认的语句终结符——分号&#xff1b;   -v 表示使用冗长模式&#xff0c;这样 DB2 会显示每一条正在执行命令的信息&#xff1b;   -f 表示其后就是脚本文件&#xff1b;   -z表示其后的信息记录文件用于记录屏幕的输出&am…...

SpringBoot + FFmpeg实现一个简单的M3U8切片转码系统

简介 在本文中&#xff0c;我们将使用SpringBoot和FFmpeg来实现一个简单的M3U8切片转码系统。M3U8是一种常用的视频流媒体播放列表格式&#xff0c;而FFmpeg则是一个强大的音视频处理工具。 技术栈 SpringBoot&#xff1a;一个基于Spring框架的快速开发平台。FFmpeg&#xf…...

SpringCloud(35):Nacos 服务发现快速入门

本小节,我们将演示如何使用Spring Cloud Alibaba Nacos Discovery为Spring cloud 应用程序与 Nacos 的无缝集成。 通过一些原生的spring cloud注解,我们可以快速来实现Spring cloud微服务的服务发现机制,并使用Nacos Server作为服务发现中心,统一管理所有微服务。 1 Spring…...

OSPF实验:配置与检测全网互通

文章目录 一、实验背景与目的二、实验拓扑三、实验需求四、实验解法1. 配置 IP 地址2. 按照图示分区域配置 OSPF &#xff0c;实现全网互通3. 检查是否全网互通 摘要&#xff1a; 本篇文章介绍了一个 OSPF&#xff08;Open Shortest Path First&#xff09;实验&#xff0c;旨在…...

常见的五种设计模式

https://www.runoob.com/design-pattern/factory-pattern.html 单例模式 **意图&#xff1a;**保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 **主要解决&#xff1a;**一个全局使用的类频繁地创建与销毁。 **何时使用&#xff1a;**当您想控制实例数目…...

pandas读取一个 文件夹下所有excel文件

我这边有个需求&#xff0c;是要求汇总一个文件夹所有的excel文件&#xff0c; 其中有.xls和 .xlsx文件&#xff0c;同时还excel文件中的数据可能还不一致&#xff0c;会有表头数据不一样需要一起汇总。 首先先遍历子文件夹并读取Excel文件&#xff1a; 使用os库来遍历包含子文…...

Python网页请求超时如何解决

在进行网络爬虫项目时&#xff0c;我们经常需要发送大量的请求来获取所需的数据。然而&#xff0c;由于网络环境的不稳定性&#xff0c;请求可能会因为超时而失败。请求超时可能导致数据获取不完整&#xff0c;影响爬虫的效率和准确性。此外&#xff0c;频繁的请求超时可能会被…...

虚幻引擎集成web前端<二>:UE4 像素流 与 web 通信

Vue 和 Unreal Engine (UE) 之间的通信可以通过多种方式实现。以下是一些建议的方法&#xff1a; 使用 Websockets&#xff1a;Websockets 是一种在客户端和服务器之间进行双向通信的技术。在 Vue 端&#xff0c;你可以使用一个 Websockets 库&#xff08;如 socket.io&#xf…...

618-基于FMC+的XCVU3P高性能 PCIe 载板 设计原理图

基于FMC的XCVU3P高性能 PCIe 载板 一、板卡概述 板卡主控芯片采用Xilinx UltraScale16 nm VU3P芯片&#xff08;XCVU3P-2FFVC1517I&#xff09;。板载 2 组 64bit 的DDR4 SDRAM&#xff0c;支持 IOX16或者 JTAG 口&#xff0c;支持PCIe X 16 ReV3.0以及 FMC 扩展接口。…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...