Java中的栈和队列

1.前言

在计算机科学中,数据结构是用来组织和存储数据的方式,以便可以高效地访问和修改。栈和队列是两种最基本的数据结构,它们在各种计算过程中都有广泛的应用。本文将介绍栈和队列的概念、特性以及它们的一些常见应用。

2.栈

2.1概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵循后进先出的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据在栈顶。

在现实中我们也有类似的场景,那就是子弹的发射,最后装填进去的子弹是最先发射出去。

2.2栈的使用

在Java中栈又是如何使用的呢?有以下这些方法。

方法功能
Stack()构造一个空的栈
E push (E e)将e入栈,并返回e
E pop()将栈顶元素出栈并返回
E peak()获取栈顶元素
int size()获取栈中有效元素个数
boolean empty()检测栈是否为空

示例: 

public static void main ( String [] args ) {
        Stack < Integer > s = new Stack ();
        s . push ( 1 );
        s . push ( 2 );
        s . push ( 3 );
        s . push ( 4 );
        System . out . println ( s . size ()); // 获取栈中有效元素个数 ---> 4
        System . out . println ( s . peek ()); // 获取栈顶元素 ---> 4
        s . pop (); // 4 出栈,栈中剩余 1 2 3 ,栈顶元素为 3
        System . out . println ( s . pop ()); // 3 出栈,栈中剩余 1 2 栈顶元素为 3
        if ( s . empty ()){
                System . out . println ( " 栈空 " );
        } else {
                System . out . println ( s . size ());
        }
}

2.3栈的实现

从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的。

2.4栈的使用场景

  1. 函数调用:每当一个函数被调用时,计算机需要记住从哪里返回到调用它的代码。这通常是通过将返回地址推入栈中来实现的。当函数执行完毕,计算机会从栈中弹出地址,并返回到该地址指示的位置继续执行。
  2. 表达式求值:在计算器程序中,栈通常用来转换和评估算术表达式。例如,在将中缀表达式(常见的算术表达式)转换为后缀表达式(便于计算的形式)时,运算符会被推入栈中,等待操作数的到来。当所有操作数都准备好后,运算符会从栈中弹出并应用于操作数。
  3. 括号匹配:在文本编辑器或编程语言解析器中,栈可以用来检查括号是否正确匹配。遇到开括号时将其推入栈中,遇到闭括号时尝试从栈中弹出一个开括号并检查是否匹配。
  4. 页面访问:在Web浏览器中,栈常用来实现前进和后退功能。当用户访问新页面时,前一个页面会被推入栈中。用户点击后退按钮时,可以从栈中弹出最近访问的页面。
  5. 递归实现:在计算机程序中实现递归算法时,每次递归调用实质上是将问题的一部分推入栈中,等待当前问题解决后再处理。递归过程的每一步都在栈上有自己的存储空间,直到达到基本情况。
  6. 数制转换:在进行数制转换时,如十进制转八进制或其他进制,可以利用栈来临时存储转换过程中产生的余数,最后从栈顶开始依次输出即得到转换结果。

2.5栈、虚拟机栈、栈帧的区别

  • 栈(Stack):在Java中,栈是一种数据结构,它遵循后进先出(LIFO)的原则。Java的集合框架中提供了Stack类,它是以向量(Vector)为基础的一个实现,用于存储和管理数据的先进后出的顺序。
  • 虚拟机栈(Virtual Machine Stack):虚拟机栈是Java虚拟机(JVM)的一部分,它是线程私有的内存区域,与线程同生同灭。虚拟机栈主要用于存储方法调用过程中的相关信息,包括方法的局部变量、返回地址等。当方法被调用时,会在虚拟机栈上创建一个新的栈帧;方法调用结束后,对应的栈帧会被销毁。
  • 栈帧(Stack Frame):栈帧是虚拟机栈中的一个元素,每次方法调用时都会创建一个栈帧。每个栈帧包含了方法的局部变量表、操作数栈、动态链接以及方法返回地址等信息。局部变量表中存储了编译期可知的各种基本数据类型及对象引用类型的变量。栈帧随方法的调用而创建,随方法执行完毕而销毁。

综上所述,栈是一种通用的数据结构,用于维护数据的先进后出顺序;虚拟机栈是JVM内部为每个线程分配的一个特定区域,用于管理方法调用过程中的数据;而栈帧则是虚拟机栈中用于记录单个方法调用信息的数据块。

3.队列

3.1概念

队列:只允许在一端进行插入数据的操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特点。

入队列:进行插入操作的一端称为队尾。

出队列:进行删除操作的一端称为队头

这就类似于生活中排队打饭的场景,排在前面的先打到饭离开队伍,队伍最后的人最后打到饭离开队伍。

3.2队列的使用

在Java中,Queue是个接口,其底层是通过链表来实现的。

常见的方法及功能:

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素的个数
boolean isEmpty()检测队列是否为空

3.2队列的模拟实现

队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,那么会选择顺序结构还是链式结构呢?

选择顺序结构还是链式结构实现队列,取决于具体的应用场景和需求。以下是两种实现方式的优缺点分析:

  • 顺序队列的优点:

内存使用效率高:顺序队列通常使用数组实现,内存空间连续,利用率高。
便于随机访问:数组的特性使得可以在常数时间内随机访问任何元素。
操作简便:在队尾插入和队头删除操作的时间复杂度为O(1)。

  • 顺序队列的缺点:

可能出现假溢出:当队列没有满但因为尾指针达到数组边界而无法插入新元素时。
大小固定:需要预先定义队列的大小,不利于动态变化的数据量。

  • 链式队列的优点:

大小动态可变:不需要预先定义大小,可以根据需要动态增长。
不存在假溢出问题:链表的特性使得即使队列看起来已满,仍然可以继续添加元素。

  • 链式队列的缺点:

内存使用效率低:由于链表需要额外的指针信息,会有额外的内存开销。
不便于随机访问:链表不支持快速的随机访问,只能按序遍历。

综上所述,如果对内存使用效率和随机访问有较高要求,且能够接受固定大小的限制,那么顺序队列(特别是循环队列)可能是更好的选择。如果应用需要队列大小能够动态变化,或者对假溢出问题敏感,那么链式队列可能更适合。在实际应用中,应根据具体需求选择合适的数据结构来实现队列。


public class Queue {
    // 双向链表节点
    public static class ListNode{
        ListNode next;
        ListNode prev;
        int value;ListNode(int value){
            this.value = value;
        }
    }
    ListNode first; // 队头
    ListNode last; // 队尾
    int size = 0;
    // 入队列---向双向链表位置插入新节点
    public void offer(int e){
    ListNode newNode = new ListNode(e);
    if(first == null){
        first = newNode;
    // last = newNode;
    }else{
        last.next = newNode;
        newNode.prev = last;
    // last = newNode;
    }
    last = newNode;
    size++;
}
// 出队列---将双向链表第一个节点删除掉
public int poll(){
// 1. 队列为空
// 2. 队列中只有一个元素----链表中只有一个节点---直接删除
// 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除
    int value = 0;
    if(first == null){
        return null;
    }else if(first == last){
        last = null;
        first = null;
    }else{
        value = first.value;
        first = first.next;
        first.prev.next = null;
        first.prev = null;
    }
    --size;
    return value;
}
// 获取队头元素---获取链表中第一个节点的值域
public int peek(){
    if(first == null){
    return null;
    }
    return first.value;
}
    public int size() {
        return size;
    }
    public boolean isEmpty(){
        return first == null;
    }
}

3.3循环队列

实际情况中有时还会使用一种队列叫循环队列。环形队列通常使用数组实现。

数组下标循环的小技巧

  • 下标最后再往后(offset小于array.length):index=(index+offset)%array.length

  • 下标最前再往前(offset小于array.length):index=(index+array.length-offset)%array.length

如何区分空与满

  • 通过添加size属性记录
  • 保留一个位置
  • 使用标记

3.4双端队列

双端队列是指允许两端都可以进行入队和出队操作的队列,那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque是一个接口,使用时必须创建LinkedList的对象。

在实际情况中,使用Deque接口是比较多的,栈和队列均可使用该接口,

总结

栈和队列是构建更复杂数据结构的基础,如二叉树、图、堆等。它们在不同的算法和系统设计中扮演着关键角色。理解它们的工作原理和应用场景对于任何希望深入学习计算机科学的人来说都是必不可少的。通过掌握这些基本概念,我们可以更好地理解和设计复杂的系统,从而解决实际问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue实现多角色登录,Vue-Router路由守卫控制权限页面

实现页面侧边栏和头部不变&#xff0c;当点击某个功能时&#xff0c;只有主体部分发生变化&#xff0c;这要用到子路由技术 我的项目结构如上&#xff0c;其中包含侧边栏和头部的文件是Manage.vue&#xff0c;主页面是Home.vue&#xff0c;个人页面是Person.vue&#xff0c;用户…

kaggle咖啡销售分析案例侧重可视化折线图条形图扇形图柱状图

目录 概述 环境依赖 数据描述 代码概述 导包 数据读取 统计缺失值 数据结构概述 描述统计 时间轴数据转换 月交易统计直方图 周交易统计图 小时数据转换 小时折线图 销售关系可视化统计 销售占比扇形图 价格箱线图 各类别多维度条形图统计 商店位置交易量折线…

9个技巧使你的Python代码更Pythonic!

如何区分漂亮和丑陋的代码&#xff1f; 更重要的是&#xff0c;如何写出漂亮的 Python 代码&#xff1f; 本文将通过初学者容易理解的例子展示9个神话般的Python技巧&#xff0c;以帮助你在日常工作中编写更多的Pythonic程序。 01 product() 使用 product() 函数避免嵌套的…

电缆故障测试仪的操作方法有哪些?

电缆故障测试仪是一种专业设备&#xff0c;用于检测电力电缆和通信电缆的各种故障。它采用多种技术手段&#xff0c;包括但不限于低压脉冲法、高压闪络法、直闪法和冲闪法。这些方法适用于不同类型的电缆故障&#xff0c;例如断线、接触不良、低阻接地、高阻接地、开路故障和短…

iOS开发 刻度盘 仪表盘,圆点按钮滑动控制,渐变色

最近项目需要&#xff0c;想做一个渐变色的刻度盘&#xff0c;圆形按钮滑动控制&#xff0c;所以 用oc写了一下&#xff0c;代码没附上&#xff0c;想看代码可以私信联系&#xff0c;效果如下图。 部分代码 self.drawCenter CGPointMake(self.frame.size.width / 2.0, self.f…

ubuntu22.04搭建dns内网

近期&#xff0c;需要在无网络的ubuntu环境下搭建内部可用的dns内网&#xff0c;总共花费3个工作日晚上&#xff0c;总算成功搭建&#xff0c;做个记录&#xff0c;记录踩坑记录&#xff0c;同时方便以后翻阅。 安装软件包&#xff1a; 有网络环境下&#xff0c;比较简单&…

科研基础与工具(论文搜索)

免责申明&#xff1a; 本文内容只是学习笔记&#xff0c;不代表个人观点&#xff0c;希望各位看官自行甄别 参考文献 科研基础与工具&#xff08;YouTube&#xff09; 搜索论文 Google Scholar 谷歌学术 涵盖面太全了&#xff0c;都收录&#xff0c;就会有很多低质量的论文…

基于STM32F103RCT6最小系统原理图和PCB

目录 1、原理图 2、PCB 3、3D图 资料下载地址&#xff1a;基于STM32F103RCT6最小系统原理图和PCB 1、原理图 2、PCB 3、3D图

解决Error in writing header file of the driver

在源代码里面更新了一批常规的内容&#xff0c;编译的时候遇到一个error&#xff0c;一大片都是红的。XXX是项目名称。 Description Resource Path Location Type Generator: ERROR: Error in writing header file of the driver XXX Cpu Processor Expert Problem 表面意思是…

nvm下载的node没有npm

nvm下载的node没有npm 相信大家最近可能发现自己使用的nvm下载nodejs没有npm了。 会出现这种情况&#xff1a; C:\Users\89121>nvm install 15 Downloading node.js version 15.14.0 (64-bit)... Complete Downloading npm version 7.7.6... Download failed. Rolling Bac…

门禁管理系统服务器如何内网映射让外网访问?

禁管理系统整体解决方案,可实现请假出入联动、门状态监控、电子地图、非法闯入报警、远程开门、红外防夹、智能统计等功能&#xff0c;应用非常广泛。 如果门禁管理系统部署在没有公网IP的本地服务器上&#xff0c;如何设置&#xff0c;能让外网互联网上也能登录访问内部的管理…

04 JavaScript学习:输出

JavaScript 没有任何打印或者输出的函数。 JavaScript 显示数据 JavaScript 可以通过不同的方式来输出数据&#xff1a; 使用 window.alert() 弹出警告框。使用 document.write() 方法将内容写到 HTML 文档中。使用 innerHTML 写入到 HTML 元素。使用 console.log() 写入到浏…

怎样在外网登录访问CRM管理系统?

一、什么是CRM管理系统&#xff1f; Customer Relationship Management&#xff0c;简称CRM&#xff0c;指客户关系管理&#xff0c;是企业利用信息互联网技术&#xff0c;协调企业、顾客和服务上的交互&#xff0c;提升管理服务。为了企业信息安全以及使用方便&#xff0c;企业…

SQLAIchemy 异步DBManager封装-01入门理解

前言 SQLAlchemy 是一个强大的 Python SQL 工具包和对象关系映射&#xff08;ORM&#xff09;系统&#xff0c;是业内比较流行的ORM&#xff0c;设计非常优雅。随着其2.0版本的发布&#xff0c;SQLAlchemy 引入了原生的异步支持&#xff0c;这极大地增强了其在处理高并发和异步…

C++11的更新介绍(lamada、包装器)

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 总有光环在陨落&#xff0c;总有新星在闪烁 lambda表达式 C98中的一个…

51-42 NÜWA:女娲,统一的多模态预训练模型

21年11月&#xff0c;微软、北大联合发布了NUWA模型&#xff0c;一个统一的多模态预训练模型&#xff0c;在 8 个下游任务上效果惊艳。目前该项目已经发展成为一系列工作&#xff0c;而且都公开了源代码。 Abstract 本文提出了一种统一的多模态预训练模型N̈UWA&#xff0c;该…

FPGA中按键程序设计示例

本文中使用Zynq 7000系列中的xc7z035ffg676-2器件的100MHz PL侧的外部差分时钟来检测外部按键是否按下&#xff0c;当按键被按下时&#xff0c;对应的灯会被点亮。当松开按键时&#xff0c;对应的灯会熄灭。 1、编写代码 新建工程&#xff0c;选用xc7z035ffg676-2器件。 点击…

递归——汉诺塔

汉诺塔 法国数学家爱德华卢卡斯曾编写过一个印度的古老传说&#xff1a;在世界中心贝拿勒斯&#xff08;在印度北部&#xff09;的圣庙里&#xff0c;一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候&#xff0c;在其中一根针上从下到上地穿好了由大到小的64片金…

通过拖拽动态调整div的大小

最近遇到一个需求&#xff0c;页面展示两块内容&#xff0c;需要通过拖拽可以动态改变大小&#xff0c;如下图&#xff1a; 实现思路&#xff1a;其实就是改变div样式的width&#xff0c;本质上就是Dom操作。 完整代码&#xff1a;&#xff08;基于vue2项目实践&#xff09; …

23年新算法,SAO-SVM,基于SAO雪消融算法优化SVM支持向量机回归预测(多输入单输出)-附代码

SAO-SVM是一种基于SAO雪消融算法优化的支持向量机&#xff08;SVM&#xff09;回归预测方法&#xff0c;适用于多输入单输出的情况。下面是一个简要的概述&#xff0c;包括如何使用SAO-SVM进行回归预测的步骤&#xff1a; 步骤&#xff1a; 1. 数据准备&#xff1a; 收集并准…