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

总结

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

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

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

相关文章

求不同字符个数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;char c 0;int a 0, k 0, n 0, q 0;//提示用户&#xff1b;printf("请输入一段话:…

【Java探索之旅】用面向对象的思维构建程序世界

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、初识面向对象1.1 什么是面向对象&#xff1f;1.2 面向对象与面向过程 二、类的定义…

【工厂模式】工厂方法模式、抽象工厂模式-简单例子

简单工厂模式&#xff0c;请跳转到我的另一篇博客【工厂模式】简单工厂模式-简单例子-CSDN博客 四、工厂方法模式 &#xff08;1&#xff09;这部分还是不变&#xff0c;创建一个Car接口&#xff0c;和两个实现类。 public interface Car {void name(); }public class WuLing…

贵阳市人民政府副市长刘岚调研珈和科技

4月9日&#xff0c;贵阳市人民政府副市长、党组成员刘岚一行到珈和科技走访调研&#xff0c;珈和科技总经理冷伟热情接待了考察团&#xff0c;就企业算力需求与合作&#xff0c;特色产业园区建设&#xff0c;科技成果转化落地等方面进行深入交流。 贵阳市教育局局长李波&#…

交换基础配置--单臂路由

1、创建vlan 创建vlan10 创建vlan10和vlan20 创建vlan1到vlan9 vlan1可以不用创建&#xff0c;因为交换机的所有接口默认为vlan1 本实验只需要vlan10和vlan20&#xff0c;以上只是介绍创建vlan的方法。 查看创建的vlan&#xff1a; sw2同理。接着将需要划分vlan的接口划入…

通过PyCharm平台开发Django应用程序

学会使用命令行工具开发Django应用程序是基础&#xff0c;不过更多的时候还是要借助平台开发工具。目前&#xff0c;最好的Django应用程序开发工具就是jetBrains公司推出的PyCharm平台了。 借助PyCharm开发平台&#xff0c;可以极大提高开发Django应用程序的效率&#xff0c;同…

电脑工作者缓解眼部疲劳问题的工具分享

背景 作为以电脑为主要工作工具的人群&#xff0c;特别是开发人员&#xff0c;我们每天都需要长时间紧盯着屏幕&#xff0c;进行代码编写、程序调试、资料查询等工作。这种持续的工作模式无疑给我们的眼睛带来了不小的负担。一天下来&#xff0c;我们常常会感到眼睛干涩、疲劳…

OpenHarmony 视图加载——ImageViewZoom

简介 ImageViewZoom 支持加载 Resource 或 PixelMap 图片&#xff0c;支持设置图像显示类型功能&#xff0c;支持缩放功能&#xff0c;支持平移功能&#xff0c;双击放大功能&#xff0c;可以监听图片大小&#xff0c;资源变化事件&#xff0c;支持清除显示图片功能。 效果展示…

Docker(七):容器监控工具(Portainer、CAdvisor)

一&#xff1a;轻量级可视化监控工具Portainer 可视化监控工具, 可以通过docker安装&#xff0c;用于管理和监控docker&#xff0c;基本上的docker命令都有对应的按钮来操作。 # always 表示docker重启了该容器也跟着重启 docker run -d --name portainer -p 8000:8000 -p 90…

USART(串口通信协议)

USART&#xff08;串口通信协议&#xff09; 【通信的目的】将一个设备的数据传输到另外一个设备&#xff0c;拓展硬件系统 【 通信协议】制定通信的规则&#xff0c;通信双方按照协议进行数据的收发 串口通信中各个参数的含义 【TX】 数据接收脚【RX】 数据发送脚【SCL】 …

Visual Components软件为您带来的价值 衡祖仿真

Visual Components具备丰富的3D仿真功能、快速建模能力、定制化应用程序逻辑和大量预定义组件库等多种特点&#xff0c;为自动化设备制造商、整合商、制造型公司提供简单、 快速和的设计方式&#xff0c;可以有效提高生产效率&#xff0c;并优化资源分配&#xff0c;避免制造过…

用户行为分析模型实践(四)—— 留存分析模型

作者&#xff1a;vivo 互联网大数据团队- Wu Yonggang、Li Xiong 本文是vivo互联网大数据团队《用户行为分析模型实践》系列文章第4篇 -留存分析模型。 本文详细介绍了留存分析模型的概念及基本原理&#xff0c;并阐述了其在产品中具体实现。针对在实际使用过程问题&#xff0…

揭秘消费增值:如何让每次购物都变得更有价值

亲爱的消费者朋友们&#xff0c;大家好&#xff01;我是微三云周丽&#xff0c;今天我将和你分享一种全新的消费理念——消费增值&#xff0c;让你的每一次消费都变得更有价值&#xff01; 在传统的消费观念中&#xff0c;我们通常只是单纯地用钱购买物品或享受服务&#xff0…

WideDeep

这里写目录标题 1. 背景2. 贡献3 模型结构&#xff08;1&#xff09;任务定义&#xff08;2&#xff09;The Wide Component&#xff08;3&#xff09;The Deep Component&#xff08;4&#xff09;联合训练Wide和Deep Model 4. 参考 1. 背景 (1) 广义线性回归通常被用于推荐模…

Scanpy(2)多种可视化

本篇内容为scanpy的可视化方法&#xff0c;可以分为三部分&#xff1a; embedding的散点图&#xff1b;用已知marker genes的聚类识别&#xff08;Identification of clusters&#xff09;&#xff1b;可视化基因的差异表达&#xff1b; 我们使用10x的PBMC数据集&#xff08;…

基于SSM的平面设计课程在线学习平台系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的平面设计课程在线学习平台系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;…

51单片机学习笔记——LED点亮

一、独立按键控制LED元器件和原理图 根据厂家给的原理图找到独立按键模块&#xff0c;观察下图我们知道按钮的一个头接GND&#xff0c;一头接IO口。由此可知我们如果需要使用第一个按钮则需要用p31。 二、独立按键控制LED程序 程序编写需要使用到IF else语句 当如果P310时P20…

盒子模型之弹性盒模型

弹性盒模型 经常适用于手机端图标布局 display: flex;让这个盒子显示成弹性盒&#xff08;很适合移动端布局&#xff09; 影响&#xff1a;1.让里面的子元素默认横向排列 2.如果子元素是行内元素&#xff0c;则直接变成块元素 3.只有一个元素&#xff0c;margin: auto;自动居中…

uni.uploadFile上传图片后台接收不到数据

今天遇到一个很奇怪的问题&#xff0c;通过使用uni.uploadFile上传文件时后端接收不到文件&#xff0c;查过很多资料&#xff0c;原来是自定义了header的Content-Type问题。取消即可&#xff0c;另把自定义文件上传的代码贴出来。 分析&#xff1a;当我们加上请求头的时候 不…

一步一步写线程之九线程池任务的窃取

一、介绍 在实际的工作安排中&#xff0c;如果有一个比较大的工作&#xff0c;又可以细分的&#xff0c;诸如有一天一万个萝卜要洗这样的工作。假如做为一个工作的分配者&#xff0c;怎么处理这种需求&#xff1f;可能每个人都会想&#xff0c;先看看一个人一天洗多少萝卜&…