数据结构——队列(java实现)及相应的oj题

文章目录

  • 前言
  • 队列
    • 队列的概念
    • 队列的实现
      • 队列的链表实现
        • 实现的方法与属性
        • 内部类实现节点
        • 入队列
        • 出队列
        • 获取队头元素但不删除
        • 判空
        • 获取队列元素个数
      • 队列的数组实现
      • 循环队列
        • 方法属性实现:
        • 构造方法
        • 向循环队列插入一个元素,成功插入则为真。
        • 从循环队列中删除一个元素,成功删除则为真
        • 从队首获取元素,如果队列为空,返回-1
        • 获取队尾元素。如果队列为空,返回 -1
        • 检查循环队列是否为空
        • 判断循环队列是否已满
    • 双端队列(Deque)
    • 队列Oj题
      • 1. [用队列实现栈](https://leetcode-cn.com/problems/implement-stack-using-queues/)
      • 2. [用栈实现队列](https://leetcode-cn.com/problems/implement-queue-using-stacks/)


前言


队列

队列的概念

队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,一种先进先出的数据结构。
队尾:允许插入的一端。
队头:允许删除的一端。

队列的实现

队列的层次实现可以是链表,也可以是数组。

队列的链表实现

队列
如果采用单链表实现,若使用头插与尾删,则出队的时间复杂度为O(n),若使用头删与尾插,且具有last标记(可看作指针),则时间复杂度为O(1).
如果采用双链表实现,则时间复杂度一定为O(1).

实现的方法与属性
public class MyQueue {ListNode first;   //创建指向队列首部的标记ListNode last;   //创建指向队列尾部的标记//入队列public void offer(int val) {}//出队列public int poll() {}//获取队头元素 但是不删除public int peek() { }//判空public boolean isEmpty() { } //获取队列元素个数public int size(){}      
}
内部类实现节点
 static  class  ListNode{//设定一个节点对象int data ;ListNode prev ;ListNode next;public ListNode(int data) {this.data = data;}}
入队列

实现思想:采用头插法,如果为空,则使得头标记与尾标记均指向新节点
不为空,则进行头插的操作。

   public void offer(int data) {//采用头插法ListNode cur = new ListNode(data);if(isEmpty()){first = last = cur;}else {cur.next = first;first.prev = cur;first = cur;}}
出队列

实现思路:

1 . 先判断队列是否为空,队列为空抛异常。
2. 队列不为空,将尾标记指向尾节点的前一个节点,然后将前一个节点的next指针置为空,删除尾结点。
因为我队入采取的是头插,所以队出采取尾删,如果大家采取尾插,则队出就采取头删了。

  public int poll() {try {if (isEmpty()) {throw new EmptyException("空队列异常!!!");}}catch (EmptyException e){e.printStackTrace();}int ret = last.data;last = last.prev;last.next = null;  // 删除尾结点return ret;}
获取队头元素但不删除

获取队头元素 但是不删除
实现思路:

1.先判断队列是否为空,队列为空抛异常。
2 .队列不为空,返回尾节点的数据。(因为我采取的是链表尾部的队首)

  public int peek() {//获取队头元素try {if (isEmpty()) {throw new EmptyException("空队列异常!!!");}}catch (EmptyException e){e.printStackTrace();}return last.data;}
判空

思想:直接返回头是否为空就行。

public boolean isEmpty(){return first == null;
}
获取队列元素个数

思想:直接遍历链表即可。

public int size(){//遍历整个链表ListNode cur = first;int count = 0 ;while (cur!=null){count++;cur = cur.next;}return  count;}

队列的数组实现

如果采用普通的数组实现队列,在下标大的一端进行插入数据,在下标小的一端删除数据,
在这里插入图片描述
我们可以在删除一个数据后,将所有的数据向左移动一位,但是时间复杂度就变成了O(N),能否用数组实现一个时间复杂度为O(1),则不浪费空间的队列呢?——即循环队列。

循环队列

循环队列图:
在这里插入图片描述
实现思想:我们有front标记指向队列的首部,用rear标记指向队列的尾部,用于指向要插入数据的位置,当下标的值超出数组长度时,便用求模计算找回对应的位置。

方法属性实现:
class MyCircularQueue {//实现的数组private  int[] elements;//指向首元素的标记int first = 0;//指向尾元素的标记int last = 0 ;//有效数组元素的个数int size = 0;//构造器,设置队列长度为 kpublic MyCircularQueue(int k) {}// 向循环队列插入一个元素。如果成功插入则返回真。public boolean enQueue(int value) {}//从循环队列中删除一个元素。如果成功删除则返回真。public boolean deQueue() {}//从队首获取元素。如果队列为空,返回 -1 public int Front() {}//获取队尾元素。如果队列为空,返回 -1 。public int Rear() {}//检查循环队列是否为空。public boolean isEmpty() {}//检查循环队列是否已满。public boolean isFull() {}
};
构造方法
 public MyCircularQueue(int k) {//用数组实现一个循环队列this.elements = new int[k];}
向循环队列插入一个元素,成功插入则为真。

实现思想:

  1. 判断队列是否已满,满了就返回false。
  2. 不满就在last处放。
  3. 在放完之后,将last的值+1然后模除队列的长度
 public boolean enQueue(int value) {//向循环队列中插入一个元素//先判断循环队列是否满if(isFull()){return false;}//未满this.elements[last] = value;last = (last+1)% elements.length;size ++;return true;}
从循环队列中删除一个元素,成功删除则为真

实现思想:

  1. 判断队列是否为空,空就返回false。
  2. 不空就直接将front指向下一个位置。
  3. 因为是循环队列,所以front+1再对数组长度进行求模。
public boolean deQueue() {//从队列中删除一个元素,删除队首的元素if(isEmpty()){return false;}//如果队列不为空,删除队首的元素,first+1,first = (first +1)% elements.length ; //必须保证first值到最大值时,能够再返回起点size = size-1;return true;}
从队首获取元素,如果队列为空,返回-1

实现思路:

  1. 先判断队列是否为空,为空返回-1。
  2. 不为空,返回front下标对应值。
  public int Front() {if(isEmpty()){return -1;}//如果队列不为空,返回队首元素return elements[first];}
获取队尾元素。如果队列为空,返回 -1

实现思想:

  1. 如果队列不为空,返回队尾元素
  2. 队尾元素的下标不一定为last -1 ,如果last 正好此时为0,那么last-1的结果为-1
    按照求模的方法:(last+数组长度-1)%数组长度,获取当前last之前的值
 public int Rear() {if(isEmpty()){return -1;}return elements[(last + elements.length-1 )%elements.length];}
检查循环队列是否为空

实现思想:通过size,判断size是否为0,来判断循环队列是否为空。

public boolean isEmpty() {//判断空,满足头标记与尾标记都相等,且无数值if( size ==0){return true;}return false;}
判断循环队列是否已满

实现思想:当front标记与last标记相同,且size不为0时,说明循环队列已满。

 public boolean isFull() {if(first ==last && size>0){return true;}return false;}
}

双端队列(Deque)

双端队列如图:
在这里插入图片描述
指可以两边都可以插入,都可以删除的队列。
Deque是一个接口,在java中有两个类实现了此接口

  1. ArrayDeque类,此类并没有在集合框架中
  2. LinkedList类
    ArrayDeque是双端队列的线性实现。
    LinkedList是双端队列的链式实现。

这两个类的对象可以当做栈与队列使用,因为他们实现了栈与队列的方法。

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

队列Oj题

1. 用队列实现栈

实现思想:
1 . 队列是先进先出操作,栈是先进后出,所以一个队列不可能实现栈,我们采用两个队列实现栈
2. 入栈,则直接将数据插入队列1即可
3. 出栈:将队列1中的size-1个元素,全部放入到队列2中去,剩余的一个元素,则进行出队即可。
如果再进行出栈,则将队2中的size-1个元素,放入到队1中去,将剩余的一个元素再进行出队
在这里插入图片描述

class MyStack {Queue<Integer> qu1 = new LinkedList<Integer>();Queue<Integer> qu2 = new LinkedList<Integer>();public MyStack() {}public void push(int x) {//将数据压入有数据的队列中if(!qu1.isEmpty()){qu1.offer(x);}else if(!qu2.isEmpty()){qu2.offer(x);}else{qu1.offer(x);}}public int pop() {//执行出栈操作,先判断栈是否为空if (empty()) {return -1;}//如果不为空if (!qu1.isEmpty()) {int len = qu1.size()-1;for (int i = 0; i < len; i++) {int val = qu1.poll();qu2.offer(val);}//return qu1.poll();}int len = qu2.size() -1 ;for (int i = 0; i < len; i++) {int val = qu2.poll();qu1.offer(val);}return qu2.poll();}public int top() {// 获取栈顶元素//将所有的数据转移到另一个队列中,期间经过一个临时变量,最后临时变量中的值即为栈顶元素if(empty()){return -1;}int val = 0;if(!qu1.isEmpty()){// for(int i=0;i<qu1.size();i++){ //有问题,当qu1执行poll方法后,会出现判断条件发生改变的情况while (!qu1.isEmpty()){val = qu1.poll();qu2.offer(val);}}else{while (!qu2.isEmpty()){val = qu2.poll();qu1.offer(val);}}return val;}public boolean empty() {if(qu1.isEmpty()&&qu2.isEmpty()){return true;}return false;}
}

2. 用栈实现队列

实现思想:

  1. 通过两个栈来实现队列
  2. 对于入队操作,直接将所有的数据放入栈1中即可
  3. 对于出队操作,则先判断栈2中是否有数据,如果有则出栈2的数据,如果没有,则将栈1中的全部数据转入栈2,然后再出栈2中的数据即可。
    在这里插入图片描述
class MyQueue {Stack<Integer> stack1 = new Stack<>();Stack<Integer> stack2 = new Stack<>();public MyQueue() {}public void push(int x) {//将所有的数据压入栈1stack1.push(x);}public int pop() {//先判断栈是否为空if(empty()){return -1;}if(!stack2.isEmpty()){//如果栈2不等于空,return stack2.pop();}//如果栈2为空while(!stack1.isEmpty()){//将栈1的元素全部压入栈2中去int val  =  stack1.pop();stack2.push(val);}return stack2.pop();}public int peek() {//获取栈顶的元素//先判断栈是否为空if(empty()){return -1;}if(!stack2.isEmpty()){//如果栈2不等于空,return stack2.peek();}//如果栈2为空while(!stack1.isEmpty()){//将栈1的元素全部压入栈2中去int val  =  stack1.pop();stack2.push(val);}return stack2.peek();}public boolean empty() {return stack1.isEmpty()==true && stack2.isEmpty() ==true ;}}

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

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

相关文章

Axivion Suite 7.8现已发布

现已实现100%覆盖MISRA规则&#xff0c;并加入了高级功能来提高代码分析能力。 我们很高兴地宣布Axivion Suite 7.8发布。全新版本的Axivion Suite对编译器、配置、分析、仪表板 (WebUI)和IDE插件的架构验证和静态代码分析功能均进行了升级。 100%覆盖所有可测试的MISRA规则 …

昇思25天学习打卡营第15天|K近邻算法实现红酒聚类

这个实验是关于如何使用MindSpore框架在红酒数据集上实现K近邻&#xff08;KNN&#xff09;算法来进行聚类分析的。KNN是一种简单但非常有效的机器学习算法&#xff0c;它通过计算样本之间的距离来决定其分类KNN算法的核心思想是&#xff0c;一个样本的类别可以通过它与训练集中…

Pytorch使用教学1-Tensor的创建

0 导读 在我们不知道什么是深度学习计算框架时&#xff0c;我们可以把PyTorch看做是Python的第三方库&#xff0c;在PyTorch中定义了适用于深度学习的张量Tensor&#xff0c;以及张量的各类计算。就相当于NumPy中定义的Array和对应的科学计算方法&#xff0c;正是这些基本数据…

【Nacos安装】

这里写目录标题 Nacos安装jar包启动Docker单体Docker集群 Nacos相关配置日志配置 Nacos安装 jar包启动 下载jar包 在官方下载链接&#xff0c;根据需求选择相应的版本下载。 解压 tar -zxvf nacos-server-2.4.0.1.tar.gz或者解压到指定目录 tar -zxvf nacos-server-2.4.0…

HarmonyOS Next原生应用开发-从TS到ArkTS的适配规则(九)

一、需要显式标注泛型函数类型实参 规则&#xff1a;arkts-no-inferred-generic-params 级别&#xff1a;错误 如果可以从传递给泛型函数的参数中推断出具体类型&#xff0c;ArkTS允许省略泛型类型实参。否则&#xff0c;省略泛型类型实参会发生编译时错误。 禁止仅基于泛型函数…

Perl脚本学习(一)-- 基础语法

系列文章目录 第一章 Perl脚本学习&#xff08;一&#xff09;-- 基础语法 一、Perl Perl 程序由声明与语句组成&#xff0c;程序自上而下执行&#xff0c;包含了循环&#xff0c;条件控制&#xff0c;每个语句以分号 ; 结束。Perl 语言没有严格的格式规范。 二、Perl简单使用…

TikTok达人合作中的消费者行为研究:精准营销新趋势

随着全球社交媒体技术的飞速发展&#xff0c;TikTok作为短视频领域的佼佼者&#xff0c;其独特的达人带货模式不仅成为驱动消费市场发展的新力量&#xff0c;还深刻改变了消费者的购买行为。本文Nox聚星将和大家探讨TikTok达人合作过程中消费者的行为模式和偏好变化。 一、消费…

SkyWalking入门搭建【apache-skywalking-apm-10.0.0】

Java学习文档 视频讲解 文章目录 一、准备二、服务启动2-1、Nacos启动2-2、SkyWalking服务端启动2-3、SkyWalking控制台启动2-4、自定义服务接入 SkyWalking 三、常用监控3-1、服务请求通过率3-2、服务请求拓扑图3-3、链路 四、日志配置五、性能剖析六、数据持久化6-1、MySQL持…

认识R与数据库连接和网络爬虫,学会在R中使用SQL语言

R语言作为一种强大的统计计算和数据分析工具,不仅在数据处理和可视化方面表现出色,还在与数据库连接和网络爬虫方面具备强大功能。本文将介绍如何在R中进行数据库连接和网络爬虫,并展示如何使用SQL语言在R中进行数据操作。 一、R与SQL数据库 1、认识SQL数据库 SQL(Struc…

企业怎么才能用上大语言模型?

题图&#xff5c;视觉中国 以ChatGPT为起点&#xff0c;大语言模型&#xff08;LLM&#xff09;用全面的技术创新&#xff0c;以及在用户和产业中的应用落地&#xff0c;再次掀起了一个AI新浪潮。 与它的前辈们相比&#xff0c;大语言模型因为打通了语言这一人类沟通中介&…

【并发编程】-4.Lock接口与AQS

Lock接口概念 概念&#xff1a;JDK1.5时&#xff0c;在Java.uitl.concurrent并发包中添加了Lock锁接口&#xff0c;其中定义了lock()、unLock()、tryLock()、lockInterruptibly()、newCondition()等一系列接口&#xff0c;它属于是JAVA语言层面的内置锁&#xff1b;特性&#…

47、PHP实现机器人的运动范围

题目&#xff1a; PHP 实现机器人的运动范围 描述&#xff1a; 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动&#xff0c;每一次只能向左&#xff0c;右&#xff0c;上&#xff0c;下四个方向移动一格&#xff0c;但是不能进入行坐标和列坐标的数位之和大于k…

探索云计算的未来:边缘计算如何重塑IT格局

目录 一、引言 二、边缘计算的基本概念与特性 1. 基本概念 2. 技术特性 三、边缘计算如何重塑IT基础设施 1. 分布式计算架构的兴起 2. 边缘节点的部署与管理 3. 数据流与业务逻辑的重新设计 4. 安全性与隐私保护的加强 四、边缘计算在关键行业的应用实践 1. 智能制造…

关联查询(xml)

多对多&#xff1a;数据库中需要有中间表&#xff0c;在两个实体类中都加入对方的List集合&#xff0c;在写查询语句时写三张表

MySQL第一阶段:多表查询、事务

继续我的MySQL之旅&#xff0c;继续上篇的DDL、DML、DQL、以及一些约束&#xff0c;该到了多表查询和事务的学习总结&#xff0c;以及相关的案例实现&#xff0c;为未来的复习以及深入的理解做好知识储备。 目录 多表查询 连接查询 内连接 外连接 子查询 事务 事务简介…

RTK高精度定位终端的功能跟用途

RTK高精度定位终端是一种集成了高精度定位技术的手持或便携式设备&#xff0c;其功能和用途广泛且重要。以下是RTK高精度定位终端的主要功能和用途&#xff1a; 一、功能 高精度定位&#xff1a; RTK技术通过接收卫星信号和地面基站的差分修正数据&#xff0c;实现厘米级甚至…

开源安全信息和事件管理(SIEM)平台OSSIM

简介 OSSIM&#xff0c;开源安全信息和事件管理&#xff08;SIEM&#xff09;产品&#xff0c;提供了经过验证的核心SIEM功能&#xff0c;包括事件收集、标准化和关联。 OSSIM作为一个开源平台&#xff0c;具有灵活性和可定制性高的优点&#xff0c;允许用户根据自己的特定需…

Java Linux操作系统

1、操作系统是协助用户调度硬件工作&#xff0c;充当用户和计算机硬件之间的桥梁 2、Linux内核 提供了linux系统的主要功能 3、发行版Centos&#xff1a;内核应用程序 4、快照&#xff1a;保存虚拟机的状态&#xff0c;当虚拟机出现问题的时候&#xff0c;可以恢复原始的状态…

Excel下载模板文件和导入文件的步骤

一、配置api // 题目导入模板下载接口 export function exportTemplate() {return request({url: /edu/question/exportTemplate,method: get,//必加header: {headers: {Content-Type: application/x-download},},responseType: "blob",//必加}) } // 题目模板数据导…

华为强制恢复出厂设置后如何恢复数据?数据重生的2个方法介绍

华为作为全球知名的手机品牌&#xff0c;其产品在市场上广受欢迎。然而&#xff0c;有时由于各种原因&#xff0c;我们可能需要强制恢复出厂设置&#xff0c;这往往意味着数据的丢失。那么&#xff0c;如何在华为强制恢复出厂设置后&#xff0c;让数据“重生”呢&#xff1f;本…