一文详解「队列」,手撸队列的3种方法!

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

本文已收录至我的 Github《算法图解》系列:https://github.com/vipstone/algorithm

前面我们介绍了栈(Stack),队列和栈是比较像的一种数据结构。我们可以想象有很多辆汽车正在通过单行道的隧道,所有车辆不能插队、不能掉头,先进来的车也先出去,我们可以把这种特征的数据结构称之为队列。

队列也属于逻辑结构,所谓的物理结构是指可以将数据存储在物理空间中,比如数组和链表都属于物理数据结构;而逻辑结构则是用于描述数据间的逻辑关系的,它可以由多种不同的物理结构来实现,比如队列和栈都属于逻辑结构。

队列特性

队列中的元素必须是先进先出(First In First Out,FIFO)的,它有两个重要的方法:入队(enqueue)和出队(dequeue)。队列的入口端叫队尾(rear),出口端叫队头(front),如下图所示:


手撸队列

学习了队列的基本知识之后,接下来我们将使用代码来实现一个队列。

首先我们先使用数组来实现一个队列,它的结构如下图所示:

1.自定义队列—数组

public class MyQueue<E> {private Object[] queue; // 存储容器private int head; // 头部指针private int tail; // 尾部指针private int size; // 队列实际存储长度private int maxSize; // 最大容量public MyQueue() {// 无参构造函数,设置默认参数this.maxSize = 10;this.head = 0;this.tail = -1;this.size = 0;this.queue = new Object[this.maxSize];}public MyQueue(int initSize) {// 有参构造函数,设置参数this.maxSize = initSize;this.head = 0;this.tail = -1;this.size = 0;this.queue = new Object[this.maxSize];}/*** 查询队头元素*/public E peek() throws Exception {if (size == 0) {throw new Exception("队列中暂无数据");}return (E) this.queue[this.head];}/*** 入列*/public boolean offer(E e) throws Exception {if (tail >= (maxSize - 1)) {throw new Exception("添加失败,队列已满");}this.queue[++tail] = e;size++;return true;}/*** 出列*/public E poll() throws Exception {if (size == 0) {throw new Exception("删除失败,队列为空");}size--;return (E) this.queue[head++];}/*** 代码测试*/public static void main(String[] args) throws Exception {MyQueue queue = new MyQueue();queue.offer("Hello");queue.offer("Java");System.out.println(queue.peek());queue.poll();System.out.println(queue.poll());}
}

以上代码的执行结果如下:

Hello

Java

2.自定义队列—链表

用链表实现队列的数据结构如下图所示:


实现代码如下:

public class QueueByLinked {/*** 声明链表节点*/static class Node<E> {E item; // 当前的值Node<E> next; // 下一个节点Node(E e) {this.item = e;}}private Node firstNode; // 队头元素private Node lastNode; // 队尾元素private int size; // 队列实际存储数量private int maxSize; // 队列最大容量public QueueByLinked(int maxSize) {if (maxSize <= 0) throw new RuntimeException("队列最大容量不能为空");// 默认初始化函数firstNode = lastNode = new Node(null);this.size = 0;this.maxSize = maxSize;}/*** 判断队列是否为空*/public boolean isEmpty() {return size == 0;}/*** 入列*/public void offer(Object e) {// 最大值效验if (maxSize <= size) throw new RuntimeException("队列已满");Node node = new Node(e);lastNode = lastNode.next = node; // 设置最后一个节点和倒数第二个节点的 nextsize++; // 队列数量 +1}/*** 出列*/public Node poll() {if (isEmpty()) throw new RuntimeException("队列为空");size--; // 队列数量 -1return firstNode = firstNode.next; // 设置并返回队头元素(第一个节点是 null,当前元素则为 Node.next)}/*** 查询队头元素*/public Node peek() {if (isEmpty()) throw new RuntimeException("队列为空");return firstNode.next;  // 返回队头元素(第一个节点是 null,当前元素则为 Node.next)}/*** 代码测试*/public static void main(String[] args) {QueueByLinked queue = new QueueByLinked(10);queue.offer("Hello");queue.offer("JDK");queue.offer("Java");System.out.println(queue.poll().item);System.out.println(queue.poll().item);System.out.println(queue.poll().item);}
}

以上代码的执行结果如下:

Hello

JDK

Java

3.扩展:使用 List 实现自定义队列

除了以上两种方式之外,我们还可以使用 Java 自身的数据结构来实现队列,比如 List,我们这里提供一个实现的思路(但并不建议在实际工作中使用),实现代码如下:

import java.util.ArrayList;
import java.util.List;/*** 自定义队列(List方式)*/
public class QueueByList<E> {private List value; // 队列存储容器public QueueByList() {// 初始化value = new ArrayList();}/*** 判断队列是否为空*/public boolean isEmpty() {return value.size() == 0;}/*** 入列*/public void offer(Object e) {value.add(e);}/*** 出列*/public E poll() {if (isEmpty()) throw new RuntimeException("队列为空");E item = (E) value.get(0);value.remove(0);return item;}/*** 查询队头元素*/public E peek() {if (isEmpty()) throw new RuntimeException("队列为空");return (E) value.get(0);}/*** 代码测试*/public static void main(String[] args) {QueueByList queue = new QueueByList();queue.offer("Hello");queue.offer("JDK");queue.offer("Java");System.out.println(queue.poll());System.out.println(queue.poll());System.out.println(queue.poll());}
}

以上代码的执行结果如下:

Hello

JDK

Java

队列使用场景

队列的常见使用场景有:

  • 存储多线程中等待排队执行的任务;

  • 存储多线程公平锁中等待执行任务的线程;

  • 常见消息中间件的任务队列等。

总结

通过以上三种队列的实现方式我们可以看出,任意容器都是可以用来实现队列(Queue)的,只要保证队列的元素先进先出(FIFO),并且在实现类中需要包含队列的四个核心方法:入列、出列、查询队列是否为空、返回队头元素等,就可以称为实现了一个自定义的队列。

最后,给大家留一个问题:队列的类型都有哪些?欢迎评论区留言~


往期推荐

动图演示:手撸堆栈的两种实现方法!


链表反转的两种实现方法,后一种击败了100%的用户!


算法图解:如何找出栈中的最小值?


算法图解:如何判断括号是否有效?


关注我,每天陪你进步一点点!

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

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

相关文章

Oracle11完全卸载方法

一、在oracle11G以前卸载oracle会存在卸载不干净&#xff0c;导致再次安装失败的情况&#xff0c;在运行services.msc打开服务&#xff0c;停止Oracle的所有服务。二、 oracle11G自带一个卸载批处理\app\Administrator\product\11.2.0\dbhome_1\deinstall\deinstall.bat运行该批…

斐波拉切数列

问题陈述&#xff1a; Fibonacci为1200年代的欧洲数学家&#xff0c;在他的著作中曾经提到&#xff1a;若有一只兔子每个月生一只小兔子&#xff0c;一个月后小兔子也开始生产。起始只有一只兔子&#xff0c;一个月后就有两只兔子&#xff0c;二个月后有三只兔子&#xff0c;三…

自定义设置一个屏保程序

用C语言写一个简单的窗口程序&#xff0c;目的是生成一个可视化的图形窗口&#xff0c;需要用到EasyX库&#xff0c;可在文章末尾的网盘链接中下载。该程序退出需左击鼠标&#xff0c;否则无法退出。 #include<stdio.h> #include<stdlib.h> #include<windows.h…

JavaScript中带示例的字符串search()方法

字符串search()方法 (String search() Method) search() is method is a String method, it is used to check whether a substring exists in the given string or not. It returns the starting index of the substring from the string where substring exists. If substrin…

漫画:如何找到链表的倒数第n个结点?

————— 第二天 —————什么意思呢&#xff1f;我们以下面这个链表为例&#xff1a;给定链表的头结点&#xff0c;但并不知道链表的实际长度&#xff0c;要求我们找到链表的倒数第n个结点。假设n3&#xff0c;那么要寻找的结点就是元素1&#xff1a;如何利用队列呢&…

转:开源图形库 c语言-图形图像库 集合

Google三维API O3DO3D 是一个开源的 Web API 用来在浏览器上创建界面丰富的交互式的 3D 应用程序。这是一种基于网页的可控3D标准。此格式期望真正的基于浏览器&#xff0c;独立于操作系统之外&#xff0c;并且支持主流的3D显卡&#xff0c;这样就可以在网页中实现效果逼真的3D…

cacti添加I/O监控

首先下载snmpdiskio-0.9.6.zip,文件不好找&#xff0c;我已经放在本文章的附件里面。解压snmpdiskio-0.9.6.zip复制partition.xml到cacti/resource/snmp_queries/下面[roottest]# cp partition.xml /home/wwwroot/default/cacti/resource/snmp_queries/分别导入模板文件&#x…

数组中的reverse_数组reverse()方法以及JavaScript中的示例

数组中的reverseJavaScript reverse()方法 (JavaScript reverse() method) reverse() method is used to reverse the order of the elements in an array, it changes the actual array and also returns an array with reversed elements. reverse()方法用于反转数组中元素的…

磊哥私藏书单分享,160买400的书!

程序员的节日&#xff08;10.24&#xff09;到了&#xff0c;当当的活动也搞起来了&#xff0c;作为有上进心的你&#xff0c;怎么可能停止学习和进步呢&#xff1f;所以磊哥在当当满 400 元减 200 元的基础上&#xff0c;有要了一个减 40 的劵&#xff0c;也就是只需要花 160 …

ORACLE中使用递归查询

在数据库查询中常常会碰到要查询树形结构的数据&#xff0c;需要用一个字段的数据当做下一条记录的父节点继续查询&#xff0c;如果在不知道有多少级节点的情况下一次次手写SQL查询会很繁琐而没有效率&#xff0c;这时可以使用 oracle中的connect with prior递归算法&#xff1…

linux——回射服务器

回射服务器即客户端发送一段数据给服务器&#xff0c;服务器再将这段数据原封不动的发送给客户端&#xff0c;原理很简单&#xff0c;原理图如下&#xff1a; 以TCP协议为例&#xff0c;客户端、服务器代码如下&#xff1a; ** 服务器&#xff1a; ** #include <stdio.h…

Android 5.0 API 的变化——开发人员注意

Android 5.0 API变化译自 http://developer.android.com/intl/zh-cn/about/versions/android-5.0.html —— By NashLegendSample示例在这里找&#xff1a;https://github.com/googlesamples/原译文在我的github上&#xff1a;https://github.com/NashLegend/ProjectBabel/blob…

dbms标识符无效_DBMS中的聚合运算符(分组依据和具有子句)

dbms标识符无效综合运营商 (Aggregate Operators) To calculate aggregate values, one requires some aggregate operators to perform this task. These operators run over the columns of a relation. The total number of five aggregate operators is supported by SQL a…

Java中的5大队列,你知道几个?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;本文已收录至 https://github.com/vipstone/algorithm 《算法图解》系列。通过前面文章的学习《一文详解「队列」&#xff0…

mysql中int、bigint、smallint 和 tinyint的区别与长度

各种整形&#xff0c;总结留作参考。bigint从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型数据&#xff08;所有数字&#xff09;。存储大小为 8 个字节。int从 -2^31 (-2,147,483,648) 到 2^31 – 1 (2,147,483,647) 的整型数据&#xff08;所有数字…

linux——回射服务器多并发(多进程)

多并发原理如图&#xff0c;多个客户端连接一个服务器&#xff0c;无论哪个客户端发送数据给服务器&#xff0c;服务器都能把数据准确的返回给这个客户端。 在socket编程中&#xff0c;socket这种文件描述符被默认设置为阻塞&#xff0c;故而read函数和accept函数时阻塞函数&a…

算法图解:如何用两个栈实现一个队列?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;本文已收录至 https://github.com/vipstone/algorithm 《算法图解》系列。队列和栈是计算机中两个非常重要的数据结构&#…

notepad++ 偶数行_C ++程序查找前N个偶数的立方和

notepad 偶数行The problem is we have a number N and we have to find sum of first N Even natural numbers. 问题是我们有一个数N &#xff0c;我们必须找到前N个偶数自然数之和。 Example: 例&#xff1a; Input:n 3Output:288 (2^3 4^36^3)A simple solution is give…

Auto activation triggers for Java(代码提示)功能扩展

1.打开Eclipse 后“window”→“Preferences”&#xff0c;选择“java”&#xff0c;展开&#xff0c;“Editor”&#xff0c;选择“Content Assist”。2.选择“Content Assist”&#xff0c;然后看到右边&#xff0c;右边的“Auto-Activation”下面的“Auto Activation trigge…

Linux——回射服务器多并发(多线程)

多线程与多进程的做法区别不大&#xff0c;思路一样&#xff0c;都是执行两个死循环&#xff0c;一个循环等待客户端连接&#xff0c;一个循环与客户端通信。多进程的方式请点此处 服务器 #include <sys/socket.h> #include <pthread.h> #include <unistd.h&g…