不良人系列-复兴数据结构(栈和队列)

 个人主页:爱编程的小新☆ 

不良人经典语录:“相呴相济 玉汝于成 勿念 心安”

目录

一. 栈(stack)

1. 栈的概念

2. 栈的常见方法

3.栈的模拟实现

 ​编辑

二. 队列

1. 队列的概念

2. 队列的使用

 2.1 队列的常见方法

2.2 队列的模拟实现

 2.3 队列的分类

(1) 普通队列

(2) 循环队列 

 (3) 双端队列

 三. 栈和队列的优缺点

1. 栈的优缺点

 2. 队列的优缺点


一. 栈(stack)

栈是一种重要的数据结构,接下来我们来看看什么是栈

1. 栈的概念

栈是一种只能在一端进行插入和删除操作的特殊线性表,进行数据操作的一端称作栈顶,那么在另一端则称为栈底,它采用后进先出的原则存储数据,即最后插入的数据最先被取出。

栈的基本操作:

  • 入栈/压栈/进栈(push):将新的元素插入到栈顶
  • 出栈(pop):删除栈顶元素并返回其的值
  • 查看栈顶元素(peek):返回栈顶元素但是不删除它
  • 判断栈是否为空:(isEmpty):若栈为空返回true,否则返回false
  • 获取栈的大小(size):返回栈中元素的个数

 栈在生活中的例子:

比如我们的羽毛球桶,后放进的球会先被取出(统一往球头的方向出); 

2. 栈的常见方法

方法功能
Stack()

构造一个空的栈

E push(E  e)将e放入栈,并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素
int size()获取栈中有效元素个数
boolean empty()检测栈是否为空
public static void main(String[] args) {Stack<Integer> stack=new Stack<>();//将元素放入栈stack.push(1);stack.push(2);stack.push(3);stack.push(4);stack.push(5);System.out.println(stack);//1,2,3,4,5System.out.println(stack.size());//栈中有效元素个数:5System.out.println(stack.peek());//栈顶元素:5stack.pop();//5出栈System.out.println(stack.isEmpty());//判断栈是否为空:false}

3.栈的模拟实现

从下图可以看见,Stack其实是继承了Vector,Vector和ArrayList类似都是基于数组实现的容器并且是动态的顺序表,但是不同的是:Vector是线程安全的数据结构

 

 线程安全和不安全的概念:

在多线程编程中,线程安全和线程不安全是两个重要的概念(这里了解一下即可)

  • 线程安全:指的是一段代码或者一个数据结构在多线程环境中被多个线程同时访问或者操作时,还是能够正确的运行,不会出现数据不一致、错误结果、程序崩溃等问题
  • 线程不安全:指的是一段代码或者一个数据结构在多线程环境中被多个线程同时访问或者操作时,可能出现数据竞争、数据不一致、错误结果、程序崩溃等问题,导致程序的行为不可预测。

 Stack的模拟实现:

public class Mystacks {public int []elem;//使用数组模拟实现栈public int usedsize;//有效元素的个数public Mystacks() {this.elem=new int[10];//默认栈的初始空间为10}public int size(){//获取栈中有效元素的个数return usedsize;}public void push(int value){//入栈//在入栈前我们需要判断一下栈是否满了,如果满了则需要进行扩容if(isFull()){//扩容this.elem= Arrays.copyOf(elem,elem.length*2);}elem[usedsize++]=value;}//该方法不对用户开放,设置为private权限即可private boolean isFull(){return usedsize==elem.length;}public int pop(){//删除栈顶元素,并返回//判断栈是否为空,为空则返回-1if(isEmpty()){return -1;}int val=elem[usedsize];usedsize--;return val;}public boolean isEmpty(){return usedsize==0;}public int peek(){//获取栈顶元素if(isEmpty()){throw new RuntimeException("栈为空,无法获取栈顶元素");}return elem[usedsize-1];}
}

 那么其实不止可以使用数组来实现栈,也可以使用链表来实现栈:

链式栈:使用链表来存储数据栈数据元素,每个节点包含数据域和指向下一个节点的指针域。其优点是可灵活扩展不存在栈溢出的问题,缺点是需要而外的指针空间,实现相对复杂

二. 队列

1. 队列的概念

队列也是一种特殊的线性表,它允许在表的一端进行插入操作,而在另一端进行删除操作,允许插入的一端称为队尾,允许删除的一端称为队头,元素按照先进先出的原则存储数据

 队列的基本操作:

  • 入队(offer):将元素添加到队尾
  • 出队(poll):从队头删除元素并返回值
  • 查看队头元素(peek):返回队头元素的值,但不改变队列的状态
  • 判断队列是否为空(isEmpty):若队列为空返回true,否则返回false
  • 获取队列大小(size):返回队列中元素的个数

 队列在生活中的例子:

就像一群小朋友在排队玩滑滑梯,先排队的人先玩滑滑梯,后排队的人后玩,遵循了我们队列的原则:先进先出,后进后出

2. 队列的使用

在Java中,Queue是一个接口,底层是通过链表来实现的,所以在实例化的时候必须实例化LinkedList的对象,因为LinkedList实现了Queue接口

 2.1 队列的常见方法

方法功能
boolean offer(E e)入队列
E poll ()出队列
peek()获取队头元素
int size()获取队列中有效元素的个数
boolean isEmpty()检测队列是否为空
 public static void main(String[] args) {Queue<Integer> queue=new LinkedList<>();//入队列queue.offer(1);queue.offer(2);queue.offer(3);queue.offer(4);queue.offer(5);System.out.println(queue);//1,2,3,4,5System.out.println(queue.size());//5System.out.println(queue.peek());//5queue.poll();//出队列System.out.println(queue);//2,3,4,5System.out.println("判断队列是否为空:"+queue.isEmpty());}

2.2 队列的模拟实现

在模拟实现队列之前我们来思考一下,是采用单向链表来实现队列好还是双向链表来实现队列好?

实际上双向链表才是最优的选择:

使用单向链表:在插入新元素的时间复杂度为O(n),因为我们需要遍历链表来找到最后一个元素的位置,此时的效率是没有双向链表好的

使用双向链表:在插入新元素和删除元素的时间复杂度都为O(1),可以直接通过对头指针和队尾指针进行入队和出队的操作,效率较高

public class Myqueue {static class ListNode{//定义一个内部类来充当我们的节点public int value;public ListNode next;//存放下一个节点的地址public ListNode prev;//存放前一个节点的地址public ListNode(int value) {this.value = value;}}public ListNode head=null;public ListNode last=null;public int usedsize=0;public void offer(int val){//创建新的节点ListNode node=new ListNode(val);//判断队列是否为空,如果为空将新节点的地址赋值给头节点的地址//如果不为空,将新节点添加到队尾if(isEmpty()){head=node;//头节点是该节点last=node;//尾节点也是该节点}else{last.next=node;//将node的地址赋值给当前尾节点的下一个节点地址node.prev=last;//将当前尾节点的地址赋值给node节点的前一个节点地址last=node;//将尾节点指向新节点}usedsize++;//有效元素个数++}public boolean isEmpty(){//判断队列为不为空return usedsize==0;}public int poll(){//出队// 1. 队列为空// 2. 队列中只有一个元素----链表中只有一个节点---直接删除// 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除int val = 0;if(head == null){return -1;}else if(head == last){last = null;head = null;}else{val = head.value;head = head.next;head.prev = null;}--usedsize;//将有效元素--return val;//返回删除的值}public int peek(){//获取队尾元素if(head==null){return -1;}return head.value;}public int size(){//获取队列中有效元素的个数return usedsize;}}

 2.3 队列的分类

(1) 普通队列

普通队列就是队列最基本的形式,我们模拟实现的就是普通队列,普通队列遵行先进先出的原则

(2) 循环队列 

循环队列是将队列存储空间的最后一个位置绕到第一个位置,从而形成一个环,依然遵循先进先出的原则进行操作:

循环队列的好处 :

  • 相较于普通队列,解决了顺序队列(底层用数组实现的队列)中可能出现的假溢出问题,提高了存储空间的利用率
  • 入队和出队的时间复杂度均为O(1),操作效率高
 (3) 双端队列
双端队列( deque)是指允许两端都可以进行入队和出队操作的队列,它综合了栈和队列的特点,元素可以从队头和队尾进行插入或删除,那么在集合框架中有一个Deque, deque “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。 Deque 是一个接口,使用时必须创建 LinkedList 的对象。

 三. 栈和队列的优缺点

1. 栈的优缺点

栈的优点:

  • 操作简单高效:入栈和出栈操作的时间复杂度均为O(1),能快速实现数据的插入和删除,在对时间要求严格的场景中表现出色。
  • 空间利用率高:只需动态分配内存来存储栈中的元素,无需预留大量额外空间,内存管理高效。

栈的缺点:

  • 数据访问受限:只能访问栈顶元素,若要访问其他元素,需先将栈顶元素依次出栈,操作不便且效率低。
  • 功能相对单一:主要用于数据的暂存和特定顺序的处理,在复杂数据结构和算法中,单独使用栈可能无法满足需求,需与其他数据结构配合。

 2. 队列的优缺点

队列的优点:

  • 先进先出顺序保证:严格按照先进先出原则处理数据,在模拟现实世界中的排队现象、任务调度等场景中,能确保数据处理的公平性和顺序性。
  • 多端操作灵活:双端队列等特殊队列结构支持在两端进行插入和删除操作,为数据处理提供了更多灵活性,可适应不同应用场景需求。

队列的缺点:

  • 出队操作效率问题:在某些实现方式中,出队操作可能涉及到元素的移动或指针的调整,时间复杂度可能较高,影响整体性能。
  • 空间管理复杂:在动态分配内存的队列中,频繁的入队和出队操作可能导致内存碎片产生,影响内存空间的有效利用和管理。

 以上就是本期栈和队列的全部内容啦,在此感谢大家的观看!!!

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

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

相关文章

【Linux网络】网络基础:IP协议

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ IP协议 IP协议基本概念协议头格式分片与组装网段划分子网掩码特殊的IP地址 IP地址的数量限制…

Linux正则化与三剑客速成(一)

目录 1.正则化 1.1正则表达式&#xff08;RE&#xff09; 1.2 正则表达式的注意事项 1.3正则表达式的分类 1.4 基本正则表达式 ^:表示匹配文本中以某个字符串开头的行。 $:表示匹配以某个字符串结尾的文件内的行 ^$:表示空行&#xff0c;但是在Linux中的实际的操作中一…

HarmonyOS 非线性容器LightWeightMap 常用的几个方法

LightWeightMap可用于存储具有关联关系的key-value键值对集合&#xff0c;存储元素中key值唯一&#xff0c;每个key对应一个value。 LightWeightMap依据泛型定义&#xff0c;采用轻量级结构&#xff0c;初始默认容量大小为8&#xff0c;每次扩容大小为原始容量的两倍。 集合中k…

Docker的容器

目录 1. 什么是容器&#xff1f;2. 容器的生命周期2.1 容器处理OOM事件2.2 容器异常退出2.3 容器暂停 3. 容器命令详解3.1 容器命令清单3.2 docker create命令3.3 docker run命令3.4 docker ps命令3.5 docker logs命令3.6 docker attach命令3.7 docker exec命令3.8 docker stat…

LearnOpenGL学习(高级OpenGL -> 高级GLSL,几何着色器)

完整代码见&#xff1a;zaizai77/Cherno-OpenGL: OpenGL 小白学习之路 高级GLSL 内建变量 顶点着色器 gl_PointSoze : float 输出变量&#xff0c;用于控制渲染 GL_POINTS 型图元时&#xff0c;点的大小。可用于粒子系统。将其设置为 gl_Position.z 时&#xff0c;可以使点…

Excel/VBA 正则表达式归纳汇总

1.with结构。以下语句用来提取A列中的“成品”两个字前面的部分的中文&#xff0c;不含成品两个字&#xff0c;结果存放在第2列。使用了On Error Resume Next&#xff0c;表示错误时继续下一条。 Sub 提取口味() Set regx CreateObject("vbscript.regexp") On Err…

CodeMirror 如何动态更新definemode

CodeMirror 如何动态更新definemode 问题描述&#xff1a;解决方法&#xff1a; 问题描述&#xff1a; 项目中有一部分用到了CodeMirror组件&#xff0c;其高亮显示的内容需要根据最新的json动态的更新&#xff0c;需要使用definemode自定义高亮内容。 想要的效果如下&#xf…

用户发送请求后服务端i/o工作过程

华子目录 服务端i/o介绍磁盘i/o机械磁盘的寻道时间、旋转延迟和数据传输时间常见的机械磁盘平均寻道时间值常见磁盘的平均延迟时间每秒最大IOPS的计算方法 网络i/o网络I/O处理过程磁盘和网络i/o 一次完整的请求在内部的执行过程 服务端i/o介绍 i/o在计算机中指Input/Output&am…

智能人体安全防护:3D 视觉技术原理、系统架构与代码实现剖析

随着工业化程度的提高&#xff0c;生产安全已成为企业关注的重点。尤其是在一些存在禁区的工业厂区和车间&#xff0c;人员误入或违规进入将带来严重的安全隐患。为了解决这一问题&#xff0c;迈尔微视推出了智能人体安全检测解决方案&#xff0c;为企业提供全方位的人员安全监…

暂停window11自动更新

window11 的自动更新功能&#xff0c;一方面在后台占用资源&#xff0c;容易导致电脑卡顿&#xff1b;另一方面&#xff0c;“更新并关机” 和 “更新并重启” 的设置令人极其反感。很多补丁兼容性很差&#xff0c;更新后极易引发电脑蓝屏、闪屏等意想不到的 bug。 1.winR打开运…

CTF-WEB: php-Session 文件利用 [第一届国城杯 n0ob_un4er 赛后学习笔记]

step 1 搭建容器 教程 A5rZ 题目 github.com Dockerfile 有点问题,手动修复一下 FROM php:7.2-apacheCOPY ./flag /root COPY ./readflag / COPY ./html/ /var/www/html/ COPY ./php.ini /usr/local/etc/php/php.ini COPY ./readflag /readsecretRUN chmod 755 /var/www…

在Win11系统上安装Android Studio

诸神缄默不语-个人CSDN博文目录 下载地址&#xff1a;https://developer.android.google.cn/studio?hlzh-cn 官方安装教程&#xff1a;https://developer.android.google.cn/studio/install?hlzh-cn 点击Next&#xff0c;默认会同时安装Android Studio和Android虚拟机&#…

网络基础概念

目录 一、计算机网络的发展背景1、网络的定义&#xff08;1&#xff09; 独立模式&#xff08;2&#xff09;网络互联 2、局域网 LAN3、广域网 WAN4、比较局域网和广域网5、扩展 —— 域域网和互联网 二、初识协议1、协议的概念2、协议的本质3、协议分层&#xff08;1&#xff…

基于docker安装-高斯DB(opengauss)

获取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/opengauss:latest启动并配置容器 docker run --name OpenGauss --privilegedtrue --restartalways -u root -p 15432:5432 -e GS_PASSWORDEnmo123 -v /etc/localtime:/etc/localtime -v /data/OpenGaus…

web网页前后端交互方式

参考该文&#xff0c; 一、前端通过表单<form>向后端发送数据 前端是通过html中的<form>表单&#xff0c;设置method属性定义发送表单数据的方式是get还是post。 如使用get方式&#xff0c;则提交的数据会在url中显示&#xff1b;如使用post方式&#xff0c;提交…

Android:展锐T760平台camera PDAF调试

一、平台PDAF流程 目前展锐平台主要支持Shield PD Sensor、Dual PD Sensor 1、Shield PD Sensor Type1相位差和信心度结果直接从Sensor输出,不经过平台算法库。 Type2Sensor端抽取PD信息, 放在一块buffer输出, PDAF算法库算出相位差和信心度。 Type3Sensor端直接输出将带有…

Java从入门到工作2 - IDEA

2.1、项目启动 从git获取到项目代码后&#xff0c;用idea打开。 安装依赖完成Marven/JDK等配置检查数据库配置启动相关服务 安装依赖 如果个别依赖从私服下载不了&#xff0c;可以去maven官网下载补充。 如果run时提示程序包xx不存在&#xff0c;在项目目录右键Marven->Re…

Android显示系统(13)- 向SurfaceFlinger提交Buffer

Android显示系统&#xff08;01&#xff09;- 架构分析 Android显示系统&#xff08;02&#xff09;- OpenGL ES - 概述 Android显示系统&#xff08;03&#xff09;- OpenGL ES - GLSurfaceView的使用 Android显示系统&#xff08;04&#xff09;- OpenGL ES - Shader绘制三角…

【git、gerrit】特性分支合入主分支方法 git rebase 、git cherry-pick、git merge

文章目录 1. 场景描述1.1 分支状态 2. 推荐的操作方式方法 1&#xff1a;git merge&#xff08;保留分支结构&#xff09;方法 2&#xff1a;git rebase&#xff08;线性合并提交历史&#xff09;直接在master分支执行git merge br_feature&#xff0c;再 执行 git pull --reba…

211-基于FMC的1路1.5G ADC 1路 2.5G DAC子卡

一、板卡概述 FMC-1AD-1DA-1SYNC是我司自主研发的一款1路1G AD采集、1路2.5G DA回放的FMC、1路AD同步信号子卡。板卡采用标准FMC子卡架构&#xff0c;可方便地与其他FMC板卡实现高速互联&#xff0c;可广泛用于高频模拟信号采集等领域。 二、功能介绍 2.1 原理框图 2.2 硬件…