04. 数据结构之栈

news/2024/10/17 20:22:37/

前言

栈(stack)是一种线性数据的逻辑存储结构。栈中的元素只能先入后出(First In Last Out,简称FILO)。最早进入的元素存放的位置叫作栈底(bottom),最后进入的元素存放的位置叫作栈顶 (top)。

1. 概念

它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。如下图所示,向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。特点是先进后出在这里插入图片描述

2. 存储原理

栈是逻辑结构,底层存储结构,既可以用数组来实现,也可以用链表来实现

2.1 数组实现

栈的数组实现如下,数组实现的栈也叫顺序栈或静态栈
在这里插入图片描述

2.2 链表实现

栈的链表实现如下,链表实现的栈也叫做链式栈或动态栈
在这里插入图片描述

3. 操作

下面代码演示以数组为底层存储结构为例,链表代码逻辑类似。

3.1 定义栈

package org.wanlong.stack;/*** @author wanlong* @version 1.0* @description: 数组实现的栈* @date 2023/5/22 19:04*/
public class ArrayStack {//私有化数组,禁止外部直接访问,限制对数组的操作只能通过,提供的出栈,入栈操作实现private Object[] nums; // 数组private int count; // 栈中元素个数// 初始化数组,申请一个大小为n的数组空间public ArrayStack(int n) {this.nums = new Object[n];this.count = 0;}
}

3.2 入栈


/*** @Description:入栈操作* @Author: wanlong* @Date: 2023/5/22 19:08* @param n:  入栈元素* @return boolean**/
public boolean push(Object n) {// 数组空间不够了,直接返回false,入栈失败。 这里不扩容,后续可以完善代码实现扩容if (count >= nums.length)return false;// 将item放到下标为count的位置,并且count加一nums[count] = n;count++;return true;
}

3.3 出栈

/*** @return Object 栈顶元素* @Description:出栈操作* @Author: wanlong* @Date: 2023/5/22 19:07**/
public Object pop() {// 栈为空,则直接返回0if (count == 0) return 0;// 返回下标为count-1的数组元素,并且栈中元素个数count减一Object n = nums[count - 1];count--;return n;
}

3.4 测试类

package org.wanlong.stack;import org.junit.BeforeClass;
import org.junit.Test;/*** @author wanlong* @version 1.0* @description: 测试栈的使用* @date 2023/5/22 19:11*/
public class Client {static ArrayStack arrayStack = new ArrayStack(10);@BeforeClasspublic static void init() {//入栈两个元素arrayStack.push(1);arrayStack.push(2);arrayStack.push(23);arrayStack.push("我是栈顶元素");}@Testpublic void testPush() {arrayStack.push(1);arrayStack.push(2);}@Testpublic void testPop() {Object pop = arrayStack.pop();System.out.println("栈顶出栈元素为:" + pop);Object pop2 = arrayStack.pop();System.out.println("出栈一个后的栈顶元素为:" + pop2);}
}

3.5 运行结果

栈顶出栈元素为:我是栈顶元素
出栈一个后的栈顶元素为:23

4. 时间复杂度

  1. 入栈和出栈的时间复杂度都是O(1)
  2. 支持动态扩容的顺序栈,因为需要扩容,所以入栈的时间复杂度是O(n)

5.应用

5.1 函数调用

每进入一个函数,就会将临时变量作为一个栈入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈,我们在开发工具debug代码的典型应用。 如下图所示,即为栈帧
在这里插入图片描述

5.2 浏览器的后退功能

我们使用两个栈,X 和 Y,我们把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈X 中出栈,并将出栈的数据依次放入栈 Y。当我们点击前进按钮时,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。

6.源码

java中LinkedList 是用双向链表实现的栈,源码在前面的链表章节提到过,感兴趣可以看前面的内容。

以上,本人菜鸟一枚,如有问题,请不吝指正。


http://www.ppmy.cn/news/86627.html

相关文章

nginx反向代理缓存

背景 nginx 一般用来做反向代理和负载均衡,将客户端请求发送到后端的 jetty,并将 jetty 的响应发送给客户端。后端的 jetty 通常不止一个,nginx 根据配置来选择其中一个 jetty,比较常见的选择策略是轮询。示意图如下 启动缓存支…

谷歌浏览器被2345劫持

方法1: 打开控制面板的卸载程序,搜索2345,把那个恶心的“安全组件-2345”卸载掉!! 这个方法比修改 host 以及注册表要好使地多! 参考网址: 【小技巧】修复chrome被2345劫持 方法2: …

【利用AI让知识体系化】V8引擎相关知识

文章目录 I. 引言V8引擎的背景和概述 II. V8的设计和工作原理V8的整体设计V8的工作流程和运行机制V8在浏览器中的应用场景 III. 内存管理内存模型和内存管理策略垃圾回收机制和算法内存泄漏和内存优化 IV. JIT编译器JIT编译器的作用和优势V8的编译流程和编译器类型编译器优化技…

机器学习常识 4: 分类问题的训练与测试

摘要: 本贴以最为典型的分类问题为例, 描述训练与测试. 1. 基本概念 上午来了 60 个患者, 根据他们的各项检测指标 (即数据), 主治医生给出了诊断结论 (如是否患病, 以及患哪种病), 但不会告诉实习生诊断的方法. 实习生根据这 60 条数据, 归纳总结出了诊断模型 (方法), 这是一…

第三十七回:如何正确地显示BottomeSheet

文章目录 概念介绍显示方法使用showBottomSheet()方法使用showModalBottomSheet()方法 示例代码 我们在上一章回中介绍了 BottomSheet Widget相关的内容,本章回中将介绍 如何正确地显示BottomSheet Widget.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在上…

Java技术接单

今天给大家介绍一个阶段性(周期性)能获取一定收益的Java技术接单群,分享给大家!主要对搞Java的粉丝有帮助,因为可以赚点小钱,对Java技术的要求不高! 那些感兴趣或者想直接加技术群的我给大家讲一…

快速理解会话跟踪技术Cookie和Session

文章目录 会话跟踪技术客户端会话跟踪技术Cookie服务端会话跟踪技术Session 会话跟踪技术 会话:客服端和服务端的多次请求与响应称为会话。 会话跟踪:服务器需要识别多次请求是否来自同一浏览器,在同一次会话多次请求中共享数据。 HTTP协议是…

C++中的继承、以及赋值兼容转换。

一、继承的概念及定义 继承可以使代码复用,允许在保持原有类特性的基础上进行扩展。 举个例子:就好比我现在要封装老师、学生等这些人的属性和方法,但是这些人都有重复的属性和方法,比如name、age、sex等等,那么我可…