4.讲究先来后到的队列

news/2025/2/15 15:28:35/

概述

目标:

  1. 队列的存储结构及操作特点
  2. java中队列相关的api
  3. 基于单链表的队列实现
  4. 刷题(设计循环队列)

存储结构及特点

队列(queue) 和栈一样,代表具有一类操作特征的数据结构,拿日常生活中的一个场景举例说明,去车站的窗口买票,就要排队,先来的人就先买,后到的人就后买,先来的人排至队头,后来的人排至队尾,不允许插队,先进先出,这就是典型的队列;先进先出(First In First Out) 即 FIFO,为了方便理解队列这种数据结构,将以两幅图,第一个是队列,第二个是栈,两图作对比
在这里插入图片描述
在这里插入图片描述
总结: 队列和栈一样都属于一种操作受限的线性表,栈只允许在一端进行操作,分别是入栈和出栈,而队列跟栈很相似,支持的操作也有限,最基本的两个操作,一个叫入队对,将数据插入到队列末尾,另一个叫出队列,从队列头部取出一个数据
注意: 入队列和出队列的时间复杂度均为O(1)

队列实现

java api

队列这种数据结构在高级语言中的实现特别的丰富,成熟
Interface Queue 链接
全类名 java.util.Queue

									方法摘要
Throws exceptionReturns special value
Insertadd(e)offer(e)
Removeremove()poll()
Examineelement()peek()

链表实现队列

基于单链表实现的队列,需要两个指针:head指针和 tail 指针;它们分别指向链表的第一个 节点 ,如图所示,入队时, tail.next = new_nodetail = tail.next 即先添加到链表尾,再将 tail 指向新加的 节点,出队时, head = head.next 即将原来的第一个头节点,变为原来的第二个节点
在这里插入图片描述
实现时,将 java.util.Queue 直接复制过来
队列接口如下:

public interface Queue<E> {boolean add(E e);boolean offer(E e);E remove();E poll();E element();E peek();boolean isEmpty();
}

队列实现类如下:

public class LinkedListQueue<E> implements Queue<E> {// 队列大小int size;// 头节点Node<E> head;// 尾节点Node<E> tail;public LinkedListQueue() {}@Overridepublic boolean add(E e) {addTail(e);return true;}@Overridepublic boolean offer(E e) {addTail(e);return true;}@Overridepublic E remove() {if (size == 0) {throw new NoSuchElementException("队列为空!");}return removeHead().val;}@Overridepublic E poll() {if (size == 0) {return null;}return removeHead().val;}@Overridepublic E element() {if (size == 0) {throw new NoSuchElementException("队列为空!");}return head.val;}@Overridepublic E peek() {if (size == 0) {return null;}return head.val;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();Node<E> h = head;while (h != null) {sb.append(h.val).append("->");h = h.next;}return sb.append("null").toString();}public boolean isEmpty() {return size == 0;}private Node<E> removeHead() {Node<E> h = head;head = head.next;h.next = null;size--;return h;}private void addTail(E item) {Node<E> tmp = tail;Node<E> newNode = new Node<>(item, null);tail = newNode;if (tmp == null) {// 链表为空,即入队既是头又是尾head = newNode;} else {// tmp 此是是倒数第二个节点tmp.next = tail;}size++;}private static class Node<E> {E val;Node<E> next;public Node(E val, Node<E> next) {this.val = val;this.next = next;}}
}

测试类如下:

public static void main(String[] args) {Queue<String> queue = new LinkedListQueue();queue.add("1");queue.add("2");queue.add("3");System.out.println("队列是否为空:" + queue.isEmpty());System.out.println(queue);System.out.println("出队元素:"+queue.remove());System.out.println(queue);System.out.println("出队元素:"+queue.poll());System.out.println(queue);System.out.println("队列头元素:"+queue.peek());System.out.println(queue);}

刷题(设计循环队列)

设计循环队列
为充分利用队列空间,克服"假溢出"现象的方法是:将队列空间想象为一个首尾相接的圆环,循环队列(Circular Queue)是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列
在这里插入图片描述

在循环队列中,当队列为空时,可知 front = rear;而当所有队列空间全占满时,也有 front = rear 。为了 区别 这两种情况,假设队列使用的数组有 capacity 个存储空间,则此时规定循环队列最多只能有 capacity - 1 个队列元素,当循环队列中只剩下一个空间存储单元时,则表示队列已满;根据以上可知,队列判空条件是 front = rear ,而队列判断为满的条件是 front = (rear + 1) mod capacity ,如上图队列已满。对于固定大小的数组,只要知道队尾 rear 与队首 front ,即可计算出队列当前的长度:(rear - front + capacity) mod capacity,如下图
在这里插入图片描述

此时由公式:0 - 1 + 5 % 5 = 4 队列长度为 4

分析完来看代码

public class MyCircularQueue {private int[] data;private int front, rear;public MyCircularQueue(int k) {// 因为满队列实际上是数组少1个,所以加上1data = new int[k + 1];}public boolean enQueue(int value) {if (isFull()) {return false;}data[rear] = value;// 不能直接 rear ++ ,值会无限增大rear = getNext(rear);return true;}public boolean deQueue() {if (isEmpty()) {return false;}front = getNext(front);return true;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();sb.append("头节点下标:" + front).append(",").append("尾节点下标:" + rear).append(" ");for (int i = 0; i < this.data.length; i++) {sb.append("a[").append(i).append("] = ").append(this.data[i]).append(",");}return sb.toString();}public boolean isEmpty() {return front == rear;}public boolean isFull() {return getNext(rear) == front;}private int getNext(int cur) {// 获取当前数据的下一个数据的下标return (cur + 1) % data.length;}
}

测试如下图,队列满,然后出一个进一个,重复两次执行
在这里插入图片描述
测试

public class MyCircularQueueTest {public static void main(String[] args) {MyCircularQueue queue = new MyCircularQueue(5);System.out.println("队列是否为空:" + queue.isEmpty());queue.enQueue(1);System.out.println(queue);queue.enQueue(2);queue.enQueue(3);queue.enQueue(4);queue.enQueue(5);System.out.println(queue);System.out.println("加入是否成功!" + queue.enQueue(5));queue.deQueue();System.out.println("队列头部元素出队:" + queue);System.out.println("加入是否成功!" + queue.enQueue(6));System.out.println(queue);// -----queue.deQueue();System.out.println("队列头部元素出队:" + queue);System.out.println("加入是否成功!" + queue.enQueue(7));System.out.println(queue);}
}

结束

队列 至此就结束了,如有问题,欢迎评论区留言


http://www.ppmy.cn/news/1189444.html

相关文章

众佰诚:抖音上做生意卖什么好

随着科技的发展&#xff0c;越来越多的人开始利用网络平台进行创业。抖音作为目前最火的短视频平台之一&#xff0c;也成为了许多人选择的创业渠道。那么&#xff0c;在抖音上做生意卖什么好呢? 首先&#xff0c;我们可以考虑一些具有创新性和独特性的产品。例如&#xff0c;手…

【java学习—十】操作集合的工具类Collections(8)

文章目录 1. 操作集合的工具类&#xff1a; Collections2. 应用3. 查找、替换3.1. max 与 min3.2. 根据Comparator返回max(min) 3.3. frequency 与 replaceAll4. 同步控制 1. 操作集合的工具类&#xff1a; Collections Collections 是一个操作 Set 、List 和 Map 等集合的工具…

MySQL系列-架构体系、日志、事务

MySQL架构 server 层 &#xff1a;层包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内置函数&#xff08;如日期、时间、数学和加密函数等&#xff09;&#xff0c;所有跨存储引擎的功能都在这一层实现&am…

priority_queue 的模拟实现

priority_queue 的底层结构 我们已经学习过栈和队列了&#xff0c;他们都是用一种容器适配出来的。今天我们要学习的 prority_queue 也是一个容器适配器。在 priority_queue 的使用部分我们已经知道想要适配出 priority_queue&#xff0c;这个底层的容器必须有以下接口&#x…

React Hooks 实战案例

文章目录 一、React Hooks 简介二、React Hooks 的基本用法1. 使用 useState 创建状态2. 使用 useEffect 添加副作用 三、React Hooks 的常见问题1. 循环引用问题2. 副作用问题 四、React Hooks 实战案例1. 使用 useReducer 和 Redux&#xff1a;2. 使用 useContext&#xff1a…

flask socketio 实时传值至html上【需补充实例】

目前版本如下 Flask-Cors 4.0.0 Flask-SocketIO 5.3.6from flask_socketio import SocketIO, emit 跨域问题网上的普通方法无法解决。 参考这篇文章解决 Flask教程(十九)SocketIO - 迷途小书童的Note迷途小书童的Note (xugaoxiang.com) app Flask(__name__) socketio Sock…

vue中watch实现翻译案例

翻译案例需要向在线接口发起一个Ajax请求&#xff0c;所以需要引入axios库。当输入一个单词或者文字时自动发起翻译请求。所以可以使用watch监听器来监听属性是否变更&#xff0c;当发生变化即发起翻译请求。 // 该方法会在数据变化时调用执行 // newValue新值, oldValue老值&…

数据结构第一课-----------数据结构的介绍

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…