疯狂数据结构-栈-Java

news2024/11/25 12:31:28

概念

基本概念解读

当谈到 "栈" 时,它是一种遵循后进先出(Last In, First Out,LIFO)原则
的有序集合。这意味着最后入栈的元素首先被弹出,而最早入栈的元素最后被弹
出。
在栈中,只能对最上面的元素进行操作,其他元素都不可见,需要将上面的元素
先出栈才能访问到其他元素。

在这里插入图片描述

基本操作分析

栈的基本操作包括入栈(push)和出栈(pop)。入栈指的是向栈中添加一个元
素,使其成为新的栈顶;而出栈指的是移除栈顶的元素,使得下一个元素成为新
的栈顶。此外,还可以通过栈顶元素的读取(top)来查看当前栈顶的值,以及
判断栈是否为空(empty)。

基本操作总结

入栈(Push):将一个元素放入栈的顶部。
出栈(Pop):从栈的顶部移除一个元素,并将其返回。
获取栈顶元素(Top):返回栈的顶部元素,但不对栈进行修改。
判空(isEmpty):检查栈是否为空。
获取栈的大小(getSize):返回栈中元素的个数。

在这里插入图片描述

应用分析

实际应用分析

栈的应用相当广泛,例如函数的调用栈、浏览器的前进后退功能和计算器的后缀
表达式求值等等。在算法设计中,栈也常用于解决问题,如深度优先搜索和括号
匹配等。

在这里插入图片描述

实际应用场景

表达式求值:栈可用于将中缀表达式转换为后缀表达式,并对其进行求值。运算
符和操作数依次入栈,直到遇到更高优先级的运算符。这时,先前的运算符必须
先出栈。
递归算法:递归算法通常使用栈来实现,因为递归函数的调用过程本质上也是一
个栈结构,每次递归调用都会将当前函数的局部变量和返回地址保存在栈上。

浏览器历史记录:浏览器使用栈来跟踪用户访问不同网页的历史记录。每当用户
访问一个新页面时,该页面被推入栈中。通过后退操作,最近访问的页面会从栈
中弹出。

函数调用:函数调用通常使用栈来管理函数的调用顺序和返回地址。每当一个函
数被调用时,其相关信息(参数、局部变量等)会被压入栈,函数执行完成后将
被弹出。

撤销操作:编辑器、文本处理软件等应用中,栈可以用于实现撤销操作。每次对
文本进行修改时,相关的操作记录会被压入栈中,在用户需要撤销操作时,可以
从栈中弹出最近的修改记录,实现撤销功能。

浏览器的浏览历史:浏览器通过使用栈来记录用户的浏览历史。每当用户访问一
个新的网页时,该网页的 URL 被推入栈中,当用户点击“后退”按钮时,最近访
问的网页 URL 被弹出栈。

括号匹配:栈可以用于检查表达式中的括号是否匹配。遍历表达式,将左括号压
入栈中,当遇到右括号时,检查栈顶的左括号是否与之匹配,若匹配则继续。

需要注意的是,在使用栈时要避免两个常见的问题:栈上溢(stack overflow)和栈下溢(stack underflow)。栈上溢发生在尝试向已满的栈中插入元素时,而栈下溢发生在尝试从空栈中弹出元素时。
在这里插入图片描述

注意事项

基本注意事项

栈的初始化:在使用栈之前,需要对栈进行初始化,即为栈分配一定大小的内存
空间,并将栈的指针指向栈底。如果栈的大小事先不确定,可以动态调整栈的大
小。

入栈操作:在进行入栈操作时,需要注意判断栈是否已满。如果栈已满,则需要
进行相应的处理,如扩充栈的空间或者报错。入栈时要确保栈的指针指向栈顶,
并将要入栈的数据放入栈顶位置,同时栈顶指针要更新。

出栈操作:在进行出栈操作时,需要判断栈是否为空。如果栈为空,则需要进行
相应的处理,如报错或者返回特定的值。出栈时要确保栈的指针指向栈顶元素,
取出栈顶元素后,栈顶指针要更新。

栈的访问:栈是一种后进先出的数据结构,因此只能访问栈顶元素,无法直接访
问栈中的其他元素。如果需要访问栈中的其他元素,需要先将栈顶元素出栈,然
后再入栈其他元素,或者使用辅助栈进行操作。

栈的容量控制:由于栈的大小是有限的,对于大量数据的处理,需要合理控制栈
的容量,避免过多的数据存储在栈中,以免造成栈溢出或者浪费内存的问题。可
以根据具体需求,设定一个合适的栈的容量上限,并在入栈操作时判断栈是否超
过容量上限。

异常处理:在使用栈的过程中,可能会出现一些异常情况,如栈溢出、空栈出栈
等。需要进行异常处理,如使用try-catch语句来捕获异常并进行相应的处理。
避免程序崩溃或者逻辑错误。

内存管理:在使用栈的过程中,需要合理地管理栈的内存。当不再需要使用栈时,
需要及时释放栈所占用的内存空间,以避免内存泄漏问题。

栈的大小限制:栈的大小是有限的,具体取决于操作系统和计算机硬件的限制。
在使用栈的过程中,需要确保栈不会溢出。当递归层数过深或者栈中的数据量
过大时,可能会导致栈溢出的问题。

入栈和出栈的顺序:栈是一种遵循"先入后出"原则的数据结构,因此在进行入栈
和出栈操作时,需要确保顺序正确,否则可能会导致程序逻辑错误。

栈的线程安全性:多线程环境下,如果多个线程同时使用同一个栈,可能会导致
线程安全的问题。需要通过合适的同步机制来保证栈的操作的线程安全性,例如
使用互斥锁或者信号量等。

在这里插入图片描述

理论总结

总结来说,栈是一种简单而重要的数据结构,具有广泛的应用场景。掌握栈的基
本操作和实现方式对于理解和应用许多问题都非常有帮助。

代码实现

思路分析

栈的实现可以使用数组或链表等数据结构。在数组中,栈的底部通常对应数组的
起始位置,栈的顶部对应最后一个元素;而在链表中,栈的顶部对应链表的首个
元素。

常规操作

import java.util.EmptyStackException;

public class Stack {
    private int[] stackArray;
    private int top;
    private int minElement; // 记录栈的最小值
    
    // 构造函数,初始化栈
    public Stack(int capacity) {
        stackArray = new int[capacity];
        top = -1; // 栈顶指针初始化为-1,表示栈为空
        minElement = Integer.MAX_VALUE; // 最小值初始化为正无穷大
    }
    
    // 判断栈是否为空
    public boolean isEmpty() {
        return top == -1;
    }
    
    // 判断栈是否已满
    public boolean isFull() {
        return top == stackArray.length - 1;
    }
    
    // 入栈操作
    public void push(int data) {
        if (isFull()) {
            throw new StackOverflowError("Stack is full");
        }
        if (data < minElement) {
            // 更新最小值
            minElement = data;
        }
        stackArray[++top] = data;
    }
    
    // 出栈操作
    public int pop() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        int data = stackArray[top];
        if (data == minElement) {
            // 如果出栈的元素是最小值,更新最小值
            updateMinElement();
        }
        top--;
        return data;
    }
    
    // 获取栈顶元素
    public int top() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        return stackArray[top];
    }
    
    // 获取栈的大小
    public int size() {
        return top + 1;
    }
    
    // 清空栈
    public void clear() {
        top = -1;
        minElement = Integer.MAX_VALUE;
    }
    
    // 获取栈的最小值
    public int getMin() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        return minElement;
    }
    
    // 判断栈是否存在某个元素
    public boolean contains(int data) {
        for (int i = 0; i <= top; i++) {
            if (stackArray[i] == data) {
                return true;
            }
        }
        return false;
    }
    
    // 更新最小值
    private void updateMinElement() {
        minElement = Integer.MAX_VALUE;
        for (int i = 0; i <= top; i++) {
            if (stackArray[i] < minElement) {
                minElement = stackArray[i];
            }
        }
    }
}
上面代码中
	获取栈的最小值的操作 getMin() 和判断栈是否存在某个元素的操作 
	contains()。在 push() 方法中,新增了对栈的最小值的更新操作,
	以便在出栈时更新最小值。在 pop() 方法中,将出栈的元素与最小值
	进行比较,如果相等,则更新最小值。 updateMinElement() 方法用
	于更新最小值,它会遍历栈中的元素以找到最小值。

在这里插入图片描述

实际应用


public class ArrayStack {
    private Object[] arra
   y;
    private int top;
    private int capacity;

    public ArrayStack(int capacity) {
        this.capacity = capacity;
        this.array = new Object[capacity];
        this.top = -1;
    }

    public void push(Object element) {
        if (top == capacity - 1) {
            throw new StackOverflowError("Stack is full");
        }
        top++;
        array[top] = element;
    }

    public Object pop() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        Object element = array[top];
        array[top] = null;
        top--;
        return element;
    }

    public Object top() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        return array[top];
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public int getSize() {
        return top + 1;
    }
}
调用上面代码
public static void main(String[] args) {
    ArrayStack stack = new ArrayStack(3);
    stack.push("A");
    stack.push("B");
    stack.push("C");

    System.out.println("Size: " + stack.getSize()); // 输出:Size: 3

    System.out.println(stack.pop()); // 输出:C
    System.out.println(stack.top()); // 输出:B

    System.out.println(stack.isEmpty()); // 输出:false

    stack.push("D");
    System.out.println(stack.pop()); // 输出:D
    System.out.println(stack.pop()); // 输出:B
    System.out.println(stack.pop()); // 输出:A

    System.out.println(stack.isEmpty()); // 输出:true
}

这个代码演示了使用数组实现的栈的基本操作。你可以根据需要进行进一步扩展和优化,例如,使用链表实现栈,或实现其他更高级的功能。

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

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

相关文章

物联网(IoT):连接未来的万物之网

引言&#xff1a; 物联网&#xff08;Internet of Things&#xff0c;简称IoT&#xff09;是指通过各种智能设备和传感器&#xff0c;使物体能够互联互通、收集和共享数据的网络。随着科技的不断进步和智能设备的普及&#xff0c;物联网的应用呈现出爆发式增长&#xff0c;对各…

【文末送书 - 数据分析之pandas篇④】- DataFrame数据合并

向阳花花花花 - 个人主页 迄今所有人生都大写着失败&#xff0c;但并不妨碍我继续向前 Python 数据分析专栏 正在火热更新中 &#x1f525; 文章目录 一、concat二、append三、merge3.1 没有属性相同时3.2 只有一个属性相同时1.一对一合并2.一对多合并3.多对多合并 3.3 有多个…

爬楼梯,假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

题记&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1 阶 1 阶2 阶 示例…

mysql开启binlog并配置定期删除以及文件大小,删库跑路之数据恢复

一、开启并binlog日志并配置 1、配置文件 [mysqld] #设置3306端口 port 3306 # 设置mysql的安装目录 basedirC:\\JJS\\software\\mysql-5.7.41-winx64\\mysql-5.7.41-winx64 # 允许最大连接数 max_connections200 # 服务端使用的字符集默认为8比特编码的latin1字符集 chara…

Vue前端生成UUID

基础使用 当使用Vue.js生成UUID时&#xff0c;我们可以使用 uuid 库来帮助我们生成通用唯一标识符&#xff08;UUID&#xff09;。UUID是一个128位的唯一标识符&#xff0c;它可以用于唯一标识对象、实体或数据。 以下是在Vue.js中生成UUID的详细步骤&#xff1a; 首先&…

SpringBoot——自动装配之@Import

文章目录 前言ImportImport 的作用1、Import(MyDemo1.class) 将某个对象加载至bean容器中2、Import一个类 该类实现了ImportSelector, 重写selectImports方法该方法返回了String[]数组的对象&#xff0c;数组里面的类都会注入到spring容器当中3、Import一个类&#xff0c;该类实…

Premiere Pro 2023(23.5) Mac

Premiere Pro是一个业界领先的视频编辑软件&#xff0c;旨在帮助用户快速、高效地制作和编辑专业质量的视频内容。作为Creative Cloud套装中的一部分&#xff0c;Premiere Pro具有丰富的功能和工具&#xff0c;可应对各种视频编辑需求。 Premiere Pro的主要特点包括多个视频和音…

Unity游戏源码分享-Unity版本的经典斗地主游戏完整源码

Unity游戏源码分享-Unity版本的经典斗地主游戏完整源码 工程地址&#xff1a; https://download.csdn.net/download/Highning0007/88057828

css+js实现点击特效效果

话不多说&#xff0c;先上效果图 实现代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title…

详细进行wrnchAI 与OpenPose 的姿势检测估计系统的各项性能比较

本文将对wrnchAI 与OpenPose的性能进行比较。我们评估了人体姿势估计系统,并通过比较 wrnchAI 与 OpenPose 的以下参数来报告我们的发现: 准确性运算速度系统要求型号尺寸其他特性 移动支持跟踪支持。绿屏分割。支持应用程序开发。许可易于设置和使用披露:我们从 wrnch 收…

Java - 集合

开篇 数组和集合对比 数组的不足: 1、长度开始时必须指定&#xff0c;而且一旦指定&#xff0c;不能修改&#xff0c;灵活性不够 2、保存的必须为同一类型的元素 3、使用数组进行增删元素的方法比较麻烦 集合 1、可以动态的保存任意多个对象 2、提供一系列操作对象的方法…

基于ResNet50算法实现图像分类识别

概要 在本文中将介绍使用Python语言&#xff0c;基于TensorFlow搭建ResNet50卷积神经网络对四种动物图像数据集进行训练&#xff0c;观察其模型训练效果。 一、目录 ResNet50介绍 图片模型训练预测 项目扩展 二、ResNet50介绍 ResNet50是一种基于深度卷积神经网络&#xff…

智迪科技在创业板上市:市值约31亿元,谢伟明和黎柏松为实控人

7月17日&#xff0c;珠海市智迪科技股份有限公司&#xff08;下称“智迪科技”&#xff0c;SZ:301503&#xff09;在深圳证券交易所创业板上市。本次上市&#xff0c;智迪科技的发行价为31.59元/股&#xff0c;发行数量为2000万股&#xff0c;募资总额约为6.32亿元&#xff0c;…

多线程、高并发(理解一)

线程的简单了解 进程、线程、纤程创建线程的几种方式synchronizedvolatileAtomicXJUC 同步锁ReentrantLockCountDownLatch 倒数的门栓CyclicBarrier 复杂操作完成&#xff0c;再走后续逻辑Phaser 所有线程需要在屏障上等待才能进入下一步执行ReadWriteLockSemaphoreExchanger 线…

MQTT协议在物联网环境中的应用及代码实现解析(三)

三、使用C#PC端编程读取MQTT服务器上特定的主题信息 以下是使用C#编程利用MQTT协议接收MQTT服务器“mqtt.laobai.net”上的“laobai_topic001”主题上的订阅信息&#xff0c;并动态显示在多行文本框中的程序代码示例&#xff0c;包括完整的代码注释和编程说明&#xff1a; us…

javascript中过滤二维对象数组重复的字段并只保留唯一值(array.filter与Array.from)

javascript中过滤二维对象数组重复的字段并只保留唯一值 1.Array.filter过滤array.filter()方法 2.Array.from过滤Array.from方法 1.Array.filter过滤 在JavaScript中&#xff0c;你可以使用Array.filter()和Set数据结构来过滤二维对象数组中重复的字段&#xff0c;只保留唯一…

CSS三栏布局的几种自适应的排版方式

CSS三栏布局的几种方式&#xff0c;主要有 float、position、flex实现。 对红色、蓝色 box 设置 float&#xff0c;绿色不设。 <style>* {margin: 0;padding: 0;}.left {width: 200px;height: 300px;background-color: red;float:left;}.right {width: 200px;height: 300…

计算机图形硬件(二) 5 - 4 硬拷贝设备

我们可以使用几种格式来获得图像的硬拷贝输出。为了演示或存档&#xff0c;可以将图像文件传送到生成投影胶片、35 mm幻灯片或电影胶片的设备与服务部门。也可将图形输出到打印机或绘图仪上&#xff0c;从而在纸上打印出图像。 输出设备生成图片的质量依赖于可显示的点的大小和…

浅尝python 一

浅尝python一 一、注释二、指定数值精度三、算数运算符四、字符串格式化输出五、打印六、类型转换&#xff0c;不会改变原数据七、比较运算符综合练习 一、注释 1、单行注释&#xff0c;快捷键 command/ # 此行被注释掉 2、多行注释 本行被注释 本行被注释or""&quo…

react报错信息

报错信息 render函数里dom不能直接展示obj对象 取变量记得要有{} https://segmentfault.com/q/1010000009619339 这样在写的时候就已经执行方法了&#xff0c;所以此处用箭头函数&#xff08;&#xff09;》{}才会在点击时执行或者 遍历数据使用map来遍历&#xff0c;使用forea…