队列的概念及使用

目录

一. 概念

二. 队列的使用

 三. 队列模拟实现

四. 循环队列

五. 面试题


一. 概念

队列 :只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾( Tail/Rear 出队列:进行删除操作的一端称为 队头 Head/Front

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

在Queue接口的方法里, 我们看到有add remove element 这些是继承于Collection接口的, 而offer poll peek是接口本身的,他们的使用效果基本一致

二. 队列的使用

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。 

public static void main ( String [] args ) {
        Queue < Integer > q = new LinkedList <> ();
        q . offer ( 1 );
        q . offer ( 2 );
        q . offer ( 3 );
        q . offer ( 4 );
        q . offer ( 5 ); // 从队尾入队列
        System . out . println ( q . size ());
        System . out . println ( q . peek ()); // 获取队头元素
        q . poll ();
        System . out . println ( q . poll ()); // 从队头出队列,并将删除的元素返回
        if ( q . isEmpty ()){
                System . out . println ( " 队列空 " );
        } else {
                System . out . println ( q . size ());
        }
}

 三. 队列模拟实现

队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前面线性表的学习了解到常见的空间类型有两种:顺序结构 和 链式结构 。显然实现队列用链式结构更好, 但是用单链表还是双向链表呢?
如果使用单链表, 从队尾进, 想要找到队尾, 则需遍历一遍链表, 或需要用last指针指向队尾, 从队头出, 则需将头结点向后移动
显然, 使用双向链表更加方便.
(LinkedList 可以看做: 双向链表 栈 队列)
public class MyQueue {static class ListNode{public int val;public ListNode prev;public ListNode next;public ListNode(int val){this.val = val;}}public ListNode head;public ListNode last;//入队public void offer(int val){ListNode node = new ListNode(val);if(head == null){head = last = node;}else{last.next = node;node.prev = last;last = node;}}//出队public int poll(){if(empty()){return -1;}int val;if(head.next == null){val = head.val;head = null;last = null;return val;}val = head.val;head = head.next;head.prev = null;return val;}public boolean empty(){return head == null;}public int peek(){if(head ==null){return -1;}return head.val;}
}

四. 循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。
环形队列通常使用数组实现。

数组下标循环的小技巧

 

队尾指针向后:

rear = (rear + 偏移量) %array.length

队尾指针向前:

rear = (rear + array.length - 偏移量) %array.length

如何区分空与满
1. 通过添加 size 属性记录
2. 保留一个位置, 浪费一个空间

设计一个循环队列 链接

class MyCircularQueue {public int[] elem;public int front;public int rear;public MyCircularQueue(int k) {elem = new int[k+1];}//入队public boolean enQueue(int value) {if(isFull()){return false;}elem[rear] = value;rear = (rear+1)%elem.length;return true;}//删除队头元素public boolean deQueue() {if(isEmpty()){return false;}front = (front + 1)%elem.length;return true;}//得到队头元素public int Front() {if(isEmpty()){return -1;}return elem[front];}//得到队尾元素public int Rear() {if(isEmpty()){return -1;}int index = (rear + elem.length - 1)%elem.length;return elem[index];}public boolean isEmpty() {return front == rear;}public boolean isFull() {return (rear + 1)%elem.length == front;}
}

五. 双端队列

双端队列( deque )是指允许两端都可以进行入队和出队操作的队列, deque “double ended queue” 的简称。
那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

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

在实际工程中,使用 Deque 接口是比较多的,栈和队列均可以使用该接口。
Deque<Integer> stack = new ArrayDeque<>();// 双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();// 双端队列的链式实现

五. 面试题

1. 用队列实现栈 链接

思路:一个队列是不能实现栈的, 需要用两个队列

1. 入栈, 当两个队列都为空时, 放在第一个队列里

2. 再次入栈时, 放在不为空的队列

3. 出栈时, 出不为空的队列, 出size-1个元素, 剩下的一个就是要出栈的元素

代码:

class MyStack {private Queue<Integer> qu1;private Queue<Integer> qu2;public MyStack() {qu1 = new LinkedList<>();qu2 = new LinkedList<>();}public void push(int x) {if(empty()){qu1.offer(x);return;}if(!qu1.isEmpty()){qu1.offer(x);}else{qu2.offer(x);}}public int pop() {if(empty()){return -1;}if(!qu1.isEmpty()){int size = qu1.size();for(int i = 0;i < size-1;i++){qu2.offer(qu1.poll());}return qu1.poll();}else{int size = qu2.size();for(int i = 0;i < size-1;i++){qu1.offer(qu2.poll());}return qu2.poll();}}public int top() {if(empty()){return -1;}if(!qu1.isEmpty()){int size = qu1.size();for(int i = 0;i < size-1;i++){qu2.offer(qu1.poll());}int tmp = qu1.peek();qu2.offer(qu1.poll());return tmp;}else{int size = qu2.size();for(int i = 0;i < size-1;i++){qu1.offer(qu2.poll());}int tmp = qu2.peek();qu1.offer(qu2.poll());return tmp;}}public boolean empty() {return qu1.isEmpty() && qu2.isEmpty();}
}

2. 用栈实现队列 链接

思路:一个栈不能实现队列, 需要两个栈

1. 入队, 把数据放在第一个栈

2. 出栈, 出第二个栈的栈顶元素即可, 如果第二个栈为空, 将里面的所有元素放到第二个栈

3. 当两个栈都为空时, 说明模拟的队列为空

class MyQueue {private Stack<Integer> s1;private Stack<Integer> s2;public MyQueue() {s1 = new Stack<>();s2 = new Stack<>();}public void push(int x) {s1.push(x);}public int pop() {if(empty()){return -1;}if(s2.isEmpty()){while(!s1.isEmpty()){s2.push(s1.pop());}}return s2.pop();}public int peek() {if(empty()){return -1;}if(s2.isEmpty()){while(!s1.isEmpty()){s2.push(s1.pop());}}return s2.peek();}public boolean empty() {return s1.isEmpty() && s2.isEmpty();}
}

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

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

相关文章

2.1_7 线程的状态与转换、组织与控制

2.1_7 线程的状态与转换、组织与控制 &#xff08;一&#xff09;线程的状态与转换 &#xff08;二&#xff09;线程的组织与控制

迅为新全国产龙芯3A6000主板支持Loongnix、国产麒麟、通信、翼辉等系统

龙芯 3A6000 处理器完全自主设计、性能优异&#xff0c;代表了我国自主桌面 CPU 设计领域的最新里程碑成果。龙芯 3A6000 处理器的推出&#xff0c;说明国产 CPU 在自主可控程度和产品性能上已双双达到新高度&#xff0c;也证明了国内有能力在自研 CPU 架构上做出一流的产品。 …

[pdf]软件方法上册第二版自测题答案和解析-共144页

潘加宇 软件方法&#xff08;上&#xff09;业务建模和需求 第二版 自测题答案和解析&#xff0c;pdf文件&#xff0c;和书配套使用 已上传至CSDN资源。 也可到百度网盘下载&#xff0c;网盘地址&#xff1a; https://pan.baidu.com/s/1wEPFkJE7RUYvNUFxzAkCeQ?pwdumlc 提…

[linux][xdp] xdp 入门

xdp 全称 eXpress Data Path&#xff0c;是 linux ebpf 中的一个功能。ebpf 在内核中预留了一些插入点&#xff0c;用户可以在这些插入点插入自己的处理逻辑&#xff0c;当数据路过插入点时可以做一些预期的处理&#xff0c;具体实现方式如下&#xff1a; ① 用户编写数据处理…

@SpringBootApplication

目录 1. SpringBootApplication注解简介 2. 使用SpringBootApplication注解 3. 自定义SpringBootApplication注解 在Spring Boot中&#xff0c;SpringBootApplication是一个非常重要的注解&#xff0c;它用于开启自动配置&#xff0c;简化了我们的开发工作。本文将详细介绍这…

PCIe(二) —— 配置空间

在上一篇中,我们简单的介绍了PCIe的总体架构,设备树和主要组成部分,并且了解了如何通过lspci命令和Windows下的设备管理器来查看PCIe的系统结构。这一篇,我们来更加深入的看看PCIe中的设备相关的信息,如配置空间,来帮助我们了解PCIe和这些命令的工作原理。 1. It is all …

FLStudio20.8编曲制作软件中文版下载及功能全面介绍

一、主要功能 FL Studio 20.8&#xff0c;作为一款深受音乐制作人和作曲家喜爱的软件&#xff0c;具备多种核心功能&#xff0c;满足从创作到完成的整个音乐制作流程。 音频录制与编辑&#xff1a;用户可以轻松录制外部音频&#xff0c;如乐器演奏、人声等&#xff0c;并在软…

Java设计模式 | 七大原则之合成复用原则

基本介绍 合成复用原则&#xff08;Composite Reuse Principle&#xff09;尽量使用合成/聚合的方式&#xff0c;而不是使用继承 设计原则核心思想总结 找出应用中可能需要变化之处&#xff0c;把他们独立出来&#xff0c;不要和那些不需要变化的代码混在一起针对接口编程&…

MySQL 用户账号迁移

文章目录 前言1. 工具安装1.1 下载安装包1.2 编译安装 2. 用户迁移后记 前言 有一个典型的使用场景&#xff0c;就是 RDS 下云大多数都是通过 DTS 进行数据传输的&#xff0c;用户是不会同步到自建数据库的。需要运维人员在自建数据库重新创建用户&#xff0c;如果用户数量很多…

Python爬虫项目实战案例-批量下载网易云榜单音乐保存至本地

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

【C++】优先级队列priority_queue模拟实现仿函数

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能手撕仿函数模拟 > 毒鸡汤&#xff1a;你活得…

【c++】stack和queue模拟实现

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能手撕stack和queue模拟 > 毒鸡汤&#xff1a;…