【数据结构】特殊的线性表——栈

在这里插入图片描述
🧧🧧🧧🧧🧧个人主页🎈🎈🎈🎈🎈
🧧🧧🧧🧧🧧数据结构专栏🎈🎈🎈🎈🎈
🧧🧧🧧🧧🧧上一篇文章:从链表到LinkedList类🎈🎈🎈🎈🎈

文章目录

  • 1.前言
    • 2.栈(Stack)
    • 2.1栈的概念
    • 2.2栈的使用
    • 2.3栈的模拟实现

1.前言

什么叫栈?要搞清楚这个概念,首先要明白“栈”原来的意思,如此才能把握本质。栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈、出栈的说法。栈这个数据结构是一个特殊的线性表,他只能在栈顶进行增删操作。

2.栈(Stack)

2.1栈的概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。

下面为图片说明:
在这里插入图片描述
生活中的例子:
枪压子弹:第一发打出去的子弹是最后压进去的子弹。
在这里插入图片描述

2.2栈的使用

2.2.1栈的方法:
push()
pop()
peek()
empty()
search()
需要掌握并且使用较多的只有这三种压栈push()出栈(删除栈顶数据)pop()查看栈顶数据pop()
在这里插入图片描述
2.2.2栈方法的代码实现:

public class ArrayTest {public static void main(String[] args) {Stack<Integer> stack = new Stack<>();//push 压栈/入栈stack.push(1);stack.push(2);stack.push(3);stack.push(4);//pop 出栈(相当于删除) 满足先进后出,后进先出。int ret = stack.pop();System.out.println(ret);//peek 与出栈一样,但不会删除,只是查看栈顶的数据int ret2 = stack.peek();System.out.println(ret2);}
}

2.2.3pop方法与peek方法的区别
前者不仅会返回栈顶的数据并且会将返回的那个栈顶数据在栈中删除,使得栈中没有这个数据,后者只是会返回栈中栈顶的数据不会删除。

我们来调试这个程序来看看这两个方法的区别:
1.pop:
未执行pop方法时栈顶的数据还在栈中。
在这里插入图片描述
执行pop方法之后,栈顶的数据4就被删除了,并返回了栈顶的数据,由ret接收。
在这里插入图片描述
2.peek:
未执行peek方法时栈顶的数据在栈中。
在这里插入图片描述
执行peek方法之后,栈顶的数据4并没有被删除了,而且还返回了栈顶的数据,由ret2接收。
在这里插入图片描述

2.3栈的模拟实现

我分三种方式去模拟实现栈分别是数组、单向链表、双向链表。
2…3.1用数组的来模拟实现栈
用数组去模拟实现栈我们需要一个数组,和一个记录数组中数据的有效个数变量。
1.先创建一个类,类中成员变量有一个数组,一个记录数组中数据的有效个数变量

public class ArrayStack {public int[] elem ;public int usedSize;//记录数组中有效数据的个数public static final int DEFAULT_CAPACITY = 10;public ArrayStack() {this.elem  = new int [DEFAULT_CAPACITY];}
}

2.实现push方法
先要判断栈中数据是否满,满了需要将数组的容量扩容。

public void push (int val) {//判断栈中是否满了if(is_Full()) {//扩容this.elem = Arrays.copyOf(elem,2*elem.length);}//将数据压入栈中elem[usedSize++] = val;}public boolean is_Full () {return usedSize == elem.length;}

3.实现pop方法,首先需要判断栈中的数据是否为空,如果为空则不需要用到pop方法

 public int pop () {//判断栈中是否为空if(is_Empty()) {//抛异常throw new EmptyStackException("栈空异常!!");}//数据还是存在数组中,只是记录数组有效个数usedSize变化了,但重新压入栈的数据会覆盖之前的数据。usedSize--;return elem[usedSize];}public boolean is_Empty() {return  usedSize == 0;}

注意:这里出栈的方式是将数组的有效个数减1,事实上原先的数据还是存在数组中的,只是无法访问到而已,如果有新数据压入栈中也可以直接将之前的数据给覆盖。

4.实现peek方法首先需要判断栈中的数据是否为空,如果为空则不需要用到peek方法

public int peek() {//判断栈中是否为空if(is_Empty()) {//抛异常throw new EmptyStackException("栈空异常!!");}return elem[usedSize-1];}

5.这里我在判断栈是否为空的时候,我用到了一个抛出异常的方法,这样更直接的知道栈是否为空。
这是我实现栈为空异常的代码:

public class EmptyStackException extends RuntimeException{public EmptyStackException() {}public EmptyStackException(String message) {super(message);}
}

6.测试代码

public class ArrayTest1 {public static void main(String[] args) {ArrayStack arrayStack = new ArrayStack();arrayStack.push(1);arrayStack.push(2);arrayStack.push(3);int ret = arrayStack.pop();System.out.println(ret);int ret2 = arrayStack.peek();System.out.println(ret2);}
}

2.3.2用单向链表来模拟实现栈
1.先把这个单向链表最基本的节点结构构建出来,在这里我们采用了内部类,往大的说链表就是一个类,弹链表是由多个节点一个一个链接起来的,所以往小的说节点又是个类,该类中成员变量有存储节点的值,也有引用。

public class SinglyLinkedStack {static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;
}

2.模拟实现push方法,在这里我们需要注意的是前面我们用数组的方式来模拟实现栈的时间复杂度为O(1)所以我们在用单向链表来模拟实现栈的时间复杂度也要保证为O(1)。在单向链表中有两种方式将数据存储在链表,一种是头插法,一种是尾插法,在这里只有头插法满足我们的要求,所以我们用头插法来实现压栈方法。

public void push(int val) {ListNode node = new ListNode(val);node.next = this.head;this.head = node;}

3.模拟实现pop方法,在删除节点的时候,我们也有两个方向来删除,一个是从头节点删,一个是从尾节点删,但需要满足时间复杂度O(1),我们采用删头节点的方式来实现pop方法。

public int pop() {int ret = head.val;this.head = head.next;return ret;}

4.模拟实现peek方法,可以直接去访问头节点的值。

public int peek() {return head.val;}

2.2.3用双向链表来模拟实现栈
在模拟之前我们可以先看看在LinkedList类中是有push、pop、peek方法的。
在这里插入图片描述
我们可以直接实列化LinkedList的一个对象来使用这些方法。

public class ListTest {public static void main(String[] args) {LinkedList<Integer> stack = new LinkedList<>();stack.push(1);stack.push(2);stack.push(3);System.out.println(stack.pop());System.out.println(stack.peek());}
}

1.在模拟实现栈之前我们也需要将最基本的结构确定,和单向链表是相差不差的,只是多了一个前引用。

public class LinkedStack {static class ListNode {public int val;public ListNode prev;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;public ListNode last;
}    

2.push方法在双向链表中不管是头插还是尾插,压栈的时间复杂度都是O(1)。
2.1头插法

//1.头插法public void push1(int val) {ListNode node = new ListNode(val);if(head == null) {head = node;last = node;}else {node.next = head;head.prev =node;head= node;}}

2.2尾插法

public void push2(int val) {ListNode node = new ListNode(val);if(head == null) {head = node;last = node;}else {node.prev = last;last.next =node;last = node;}}

3.pop方法的模拟实现,不管在头节点出还是在尾节点出时间复杂度都是O(1)
3.1删头节点

public int pop1() {ListNode cur = head.next;int ret = head.val;head = cur;return ret;}

3.2删尾节点

public int pop2() {ListNode cur = last.prev;int ret = last.val;last = cur;return ret;}

4.模拟实现peek方法,采用的头插法,直接返回头节点的值,采用的尾插法,直接返回尾节点的值。
4.1头插法

public int peek1() {return head.val;}

4.2尾插法

 public int peek2() {return last.val;}

希望大家可以给我点点关注,点点赞,并且在评论区发表你们的想法和意见,我会认真看每一条评论,你们的支持就是我的最大鼓励。🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹

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

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

相关文章

torch.cuda.is_available()=False

问题&#xff1a; 显示torch.cuda.is_available()False 解决办法&#xff1a;说明这个虚拟环境不可用&#xff0c;删除虚拟环境&#xff0c;重建一个新的虚拟环境 1、删除原来的虚拟环境&#xff0c;假如原虚拟环境为pytorch-old&#xff0c;输入以下命令&#xff0c;先退出当…

vsto 打开excel同时同花顺插件自动登录报错

excelApp.Workbooks.Open(path, false); Svstem,Runtime,Interopservices,COMException(0x800706BE):远程过程调用失败。(号常来自 HRESULT:0X800706BE)在 Micosot olieieroo.Excelworbols0penstma fiename.0hiectUodatelinks 0biectReadony 0hedtfomat 0hiectPaswond. 0hectwt…

基于SWOT法的信阳本土房地产企业现状及对策分析

目 录 摘要 1 Abstract 1 1绪论 2 2信阳市房地产企业概述 2 2.1中小城市房地产企业概念 2 2.2信阳本土房地产企业定位 3 2.2.1信阳市概况 3 2.2.2信阳市城市规划 3 2.2.3信阳房地产企业概况 4 2.3信阳市本土房地产企业特点 5 2.4研究信阳市本土房地产企业的必要性 6 3运用SWOT…

KAFKA入门教程

目录 1.安装kafka 2.安装kafkamanager可视化工具 3.springboot整合kafka 1.pom导包 2.启动类和yml配置 3.代码演示 编写生产者&#xff1a; 消费者&#xff1a; 1.安装kafka 进入kafka官网下载对应版本kafka kafka官网地址&#xff1a;Apache Kafka kafka是使用Scal…

【阿里云系列】-如何实现两个VPC网络资源互通

背景 由于实际项目预算有限&#xff0c;两套环境虽然分别属于不同的专有网络即不同的VPC&#xff0c;但是希望借助一台运维机器实现对两个环境的监控和日常的运维操作 网络架构 如下是需要实现的外网架构图&#xff0c;其中希望实现UAT环境的一台windows的堡垒机可以访问生产…

Spring Cloud集成nacos配置中心

1.添加Nacos Config依赖 打开nacos-config-demo的pom.xml文件并添加以下两个依赖项 项目的配置文件中通常包括数据库连接配置项、日志输出配置项、Redis连接配置项、服务注册配置项等内容&#xff0c;如spring-cloud-alibaba-nacos-config-base-demo项目中就包含数据库连接配置…

数据守护神:自动备份数据的重要性与方案

在数字化时代&#xff0c;数据已经成为我们生活与工作的核心。无论是个人用户还是企业组织&#xff0c;数据的丢失或损坏都可能带来不可估量的损失。因此&#xff0c;自动备份数据的重要性不言而喻。自动备份数据不仅能够确保数据的实时更新和安全性&#xff0c;还能在数据丢失…

坐标变换(二维、三维)

文章目录 一、四种空间1.1 定义和对比1.2 齐次坐标系 二、刚性变换2.1 定义2.2 平移2.3 旋转2.3.1 二维2.3.1.1 绕原点2.3.1.2 绕任意点 2.3.2 三维2.3.2.1 绕x轴2.3.2.2 绕y轴2.3.2.3 绕z轴 一、四种空间 1.1 定义和对比 标量空间&#xff1a;只有标量&#xff1b;向量空间&…

使用gnvm下载nodejs和npm

目录 前言 一、下载gnvm 二、利用gnvm下载nodejs 三、下载对应版本的npm 四、gnvm常用的命令 总结 前言 由于之前下载的版本过低&#xff0c;需要升级版本。但在使用gnvm升级node版本时遇到了一系列的问题&#xff0c;索性就把nodejs全部删除&#xff0c;重新用gnvm在下…

网络请求与数据解析

urllib是Python自带的标准库中用于网络请求的库 &#xff0c;无需安装&#xff0c;直接引用即可。通常用于爬虫开发、API&#xff08;应用程序编程接口&#xff09;数据获取和测试。 urllib库的几个模块&#xff1a; urllib.request :用于打开和读取URLurllib.error:包含提出…

羊大师揭秘羊奶滋养,养生的新黄金选择

羊大师揭秘羊奶滋养&#xff0c;养生的新黄金选择 羊奶&#xff0c;这个自古以来的天然营养佳品&#xff0c;近年来逐渐受到现代人的青睐&#xff0c;成为养生的新黄金选择。它以其独特的营养价值和滋养功效&#xff0c;为追求健康生活的我们提供了全新的养生视角。 羊奶的滋…

LeetCode # 1161. 最大层内元素和

1161. 最大层内元素和 题目 给你一个二叉树的根节点 root。设根节点位于二叉树的第 1 层&#xff0c;而根节点的子节点位于第 2 层&#xff0c;依此类推。 请返回层内元素之和 最大 的那几层&#xff08;可能只有一层&#xff09;的层号&#xff0c;并返回其中 最小 的那个。…

Vue:自动按需导入element-plus图标

自动导入使用 unplugin-icons 和 unplugin-auto-import 从 iconify 中自动导入任何图标集。 完整vite.config.js参考模板 https://download.csdn.net/download/ruancexiaoming/88928539 动态导入图标参考 https://blog.csdn.net/ruancexiaoming/article/details/136568219 导入…

几个redis常用命令

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 ping&#xff1a;测试连接是否存活 例如&#xff1a;测试当前redis数据库是否存活 127.0.0.1:6379> ping #返回PONG&am…

python学习28

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

不会还有人判断字符是否为数字或字母还用Ascii吧

不会还有人判断字符是否为数字或字母还用Ascii吧 c > a && c < z) || (c > 0 && c < 9当然&#xff0c;也可也用&#xff0c;下面给大家分享几个方法快速判断。 Character.isLetter(ch) 判断ch是否为字母 Character.isDigit(ch) 判断ch是否为数字…

导入空管基础数据

1、首先将data.tar.gz解压到自定义目录中 注意&#xff1a;由于数据文件的压缩包比较大&#xff0c;解压过程可能会持续3~5分钟&#xff0c;请耐心等待。 [rootnode3 ~]# cd /opt/software/ [rootnode3 software]# tar -xzf data.tar.gz -C /opt/ 2、利用SQLyog或者其他数据库…

9、设计模式之组合模式(Composite)

一、什么是组合模式 组合模式也成为整体部分模式&#xff0c;是一种结构型设计模式。它将对象组合成树形的层次结构&#xff0c;用来表示“整体-部分”的关系。通过组合模式&#xff0c;我们可以使用相同的方式处理单个对象和多个对象组合。 二、角色组成 组件&#xff08;Com…

ROS机器人程序设计课程进度安排-2023-2024-2

进度安排由人工智能审核制定。 课程 教学进度表预期效果与课程内容详细描述 一、预期效果 此教学进度表旨在确保《ROS机器人程序设计》课程在2023&#xff5e;2024学年度第二学期内&#xff0c;按照预定的教学计划和进度&#xff0c;有序、高效地进行。通过本课程的教学&…

第二十一天-NumPy

目录 什么是NumPy NumPy使用 1.数组的创建 2.类型转换 3.赠删改查 4.数组运算 5.矩阵运算 什么是NumPy 1.NumPy操作的是多维数组&#xff0c;什么是纬度&#xff1f; NumPy使用 1. 安装 pip install numpy import numpy as np 2.官网&#xff1a; 中文官网&#xff1a…