Java中的栈和队列

news2024/11/19 13:38:48

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接口是比较多的,栈和队列均可使用该接口,

总结

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

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

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

相关文章

姑苏寻韵~庆开放原子开源大赛 OpenTiny 前端 Web 应用开发挑战赛路演圆满落幕。

春日已至&#xff0c;姑苏古城迎来了一场编程的盛宴——开放原子开源大赛OpenTiny前端Web应用开发挑战赛。历时三个月的激烈角逐&#xff0c;OpenTiny与众多开发者携手共赴这场智慧的较量。决赛路演于4月14日在苏州&#xff08;太湖&#xff09;产业软件园圆满落下帷幕~ 开放原…

编译一个基于debian/ubuntu,centos,arhlinux第三方系统

目录 前言 准备工作 下载linux源码进行编译 linux源码下载 网站 问题 解决办法 编译 可能会遇到的问题 chroot下载debian环境 进入虚拟环境 把chroot的根目录文件打包为.gz文件 编译init文件&#xff08;用于系统启动时的一系列引导&#xff09; 给予文件夹权限 …

Zabbix 监控软件(一)

通常我们服务搭建成功 但不清楚服务器的运行状况&#xff0c;这时候就需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监控软件&#xff0c;我们可以: ●通过一个友好的界…

基于java+springboot+vue实现的物业管理系统(文末源码+Lw+ppt)23-23

摘 要 快速发展的社会中&#xff0c;人们的生活水平都在提高&#xff0c;生活节奏也在逐渐加快。为了节省时间和提高工作效率&#xff0c;越来越多的人选择利用互联网进行线上打理各种事务&#xff0c;通过线上物业管理系统也就相继涌现。与此同时&#xff0c;人们开始接受方…

Leetcode算法训练日记 | day31

专题九 贪心算法 一、分发饼干 1.题目 Leetcode&#xff1a;第 455 题 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的…

如何查看项目中使用的Qt版本

如何查看项目中使用的Qt版本 1.点击左下角电脑按钮查看Qt版本。 2.点击左侧栏项目按钮查看Qt版本。

Android开发——Fragment

Demo fragment_blank.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_pare…

Windows系统远程桌面服务(RDP)的安全层和加密级别

1.【win10企业版/server2012】 1.服务器运行gpedit.msc&#xff0c;打开本地组策略&#xff0c;进入列表目录【计算机配置】-【管理模板】-【windows组件】-【远程桌面服务】-【远程桌面会话主机】-【安全】 2.双击“远程(RDP)连接要求使用指定的安全层”选项&#xff0c;配置…

Redis入门到通关之数据结构解析-RedisObject

文章目录 ☃️概述☃️源码 ☃️概述 RedisObject 是 Redis 中表示数据对象的结构体&#xff0c;它是 Redis 数据库中的基本数据类型的抽象。在 Redis 中&#xff0c;所有的数据都被存储为 RedisObject 类型的对象。 RedisObject 结构体定义如下&#xff08;简化版本&#xf…

linux负载均衡 和 系统负载分析笔记

1 负载均衡 1.1 计算负载 1.1.1 PELT算法简介 从Linux3.8内核以后进程的负载计算不仅考虑权重&#xff0c;⽽且跟踪每个调度实体的历史负载情况&#xff0c;该算法称为PELT(Per-entity Load Tracking) 《奔跑吧Linux内核》卷1&#xff1a;基础架构&#xff1b;P505 相关资料…

LeetCode216:组合总和Ⅲ

题目描述 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9 每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 解题思想 使用回溯算法 代码 class So…

Cubemx+RTL8201驱动

Cubemx 生产的驱动只能选择LAN8742&#xff0c;无法适配RTL8201&#xff0c;这篇文字就分享一下如何逐步修改lan8742的代码去适配。 一、地址问题 入口函数&#xff1a;int32_t LAN8742_Init(lan8742_Object_t *pObj) 主要是做PHY 地址检测&#xff0c;但是我们查阅RTL8201手…

2024中国国际中医药健康服务博览会(7月深圳中医药展)

聚焦中医国粹&#xff0c;助力健康中国 2024第五届中国国际中医药健康服务&#xff08;深圳&#xff09;博览会 暨粤港澳大湾区中医药高质量发展大会 邀请函 时间&#xff1a;2024年7月31日-8月2日 地址:深圳会展中心&#xff08;福田&#xff09; 支持单位&#xff…

WIFISKY 7层流控路由器 confirm.php RCE漏洞复现

0x01 产品简介 WIFISKY-7层流控路由器是一款可用于家庭或办公环境的无线路由器,具备流控功能以优化网络流量和提供更稳定的网络连接。该路由器采用了7层流控技术,能够依据网络数据包的内容进行智能管理,从而实现对网络流量的精细化控制和优化。这种技术可以提升网络的整体性…

MySQL-数据库基础

一、背景与基本使用 首先是登录方式&#xff0c;一般用 mysql -h 127.0.0.1 -P 3306 -u root -p mysql也是一种网络服务。 当然我们在本地登录时可以省去主机ip和端口号。 -h表示我们要登录mysql在哪个ip的主机上&#xff0c; -P表示端口号。 -u表示以谁的身份去登录。…

DDR的概念解读-提升速度的四把板斧

计算机以及手机系统性能的改善&#xff0c;不仅仅取决于cpu处理器主频的提升&#xff0c;还与cpu和内存之间的访问速度密切相关。 SDRAM: Synchronous Dynamic Random Access Memory,同步动态随机存取存储器&#xff0c;同步是指Memory工作需要同步时钟&#xff0c;内部命令的发…

最新热点:博弈+低碳!基于多主体主从博弈的区域综合能源系统低碳经济优化调度程序代码!

前言 随着能源需求上升及环境污染日益严重&#xff0c;安全高效、低碳清洁已成为能源发展的主流方向。在此背景下&#xff0c;统筹多能耦合、协同调度的区域综合能源系统已成为高效利用能源的重要形式。实现多能供应的安全性、经济性和灵活性的有效手段是优化RIES运行。因此&a…

vbox两步解决VirtualBox共享文件夹在Windows下的符号链接创建问题

默认情况下&#xff0c;VirtualBox 的共享文件夹特性在 Windows 下工作是有问题的&#xff0c;如果你运行一些需要符号连接&#xff08;Symlink&#xff09;的程序&#xff0c;比如默认设置的 yarn 或者 npm&#xff0c;由于 npm 包在安装之后会在 ./node_modules/.bin 创建在 …

B008-方法参数传递可变参数工具类

目录 方法参数传递可变参数冒泡排序Arrays工具类Arrays工具类常用方法 方法参数传递 /*** java中只有值传递* 基本数据类型 传递的是具体的值* 引用数据类型 传递的是地址值*/ public class _01_ParamPass {public static void main(String[] args) {// 调用方法 getSumge…

InFusion:通过从扩散先验学习深度补全来进行图像 3D 高斯修复

InFusion 以其图像条件模型超越了当前的方法&#xff0c;提供精确的深度修复并支持纹理定制和对象插入等高级应用程序。 github项目页面&#xff1a; Infusion Github 仓库&#xff1a;GitHub - ali-vilab/Infusion: Official implementations for paper: InFusion: Inpainti…