Java数据结构之队列示例详解

 更新时间:2025年12月21日 11:37:08   作者:鸽鸽程序猿  
队列是一种线性数据结构,它遵循先进先出或后近后出的原则,队列允许在一端插入元素,另一端删除元素,这篇文章主要介绍了Java数据结构之队列的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、队列

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

队尾:允许插入的一端。

队头:允许删除的一端。

二、队列的模拟实现

队列的底层可以是顺序表,可以是链表实现。

2.1 队列的链式实现

在实现队列前我们先思考使用什么样的链表来实现?

由于栈的特性是先入先出,如果使用单链表和双向链表都可以,

只要在单链表标记一下尾节点就行,

但是因为Java提供的是双向链表实现的,所以我们使用双向链表。

2.1.1 接口实现

实现的接口如下:

public class MyQueue {
	//入队列
    public void offer(int val) {}
	//出队列
    public int poll() {}
    //获取队头元素 但是不删除
    public int peek() { }
    //判空
    public boolean isEmpty() { } 
    //获取队列元素个数
    public int size(){}      
}

2.1.2 内部类

跟双向链表的内部类实现差不多。

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;

2.1.3 入队列

实现思路:

  1. 先看队列是否为空,为空,头尾指向入队节点。
  2. 不为空尾节点的后继next指向入队节点,入队节点前驱prev指向尾节点,尾节点变为入队节点。
public void offer(int val){
	ListNode cur = new ListNode(val);
	if(isEmpty()){
		head = last = cur;
		return;
	}
	last.next = newNode;
    newNode.prev = last;
    last = newNode;
}

2.1.4 出队列

实现思路:

  1. 先判断队列是否为空,队列为空抛异常。
  2. 队列不为空,将头节点记录下来,头节点后一个节点前驱prev置为空,头节点变为后一个节点。
public int poll() throws NullPointerException{
	try{
		if(isEmpty()){
			throw new NullPointerException;
		}
	}catch(NullPointerException e){
		 e.printStackTrace();
	}
	ListNode cur = head;
	head.next.prev = null;
	head = head.next;
	return cur.val;
}

2.1.5 获取队头元素 但是不删除

实现思路:

  1. 先判断队列是否为空,队列为空抛异常。
  2. 队列不为空,返回头节点。
 public int peek() throws NullPointerException{
	try{
		if(isEmpty()){
			throw new NullPointerException;
		}
	}catch(NullPointerException e){
		 e.printStackTrace();
	}
	return head.val;
}

2.1.6 判空

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

public boolean isEmpty(){
	return head == null;
}

2.1.7 获取队列元素个数

直接循环遍历即可。

    public int size(){
    	ListNode cur = head;
    	int size = 0;
		while(cur != null){
			cur = cur.next;
			size++;
		}
		return size;
	} 

2.2 队列的顺序实现(循环队列)

2.2.1 直接使用顺序表的缺陷

当我们直接使用顺序表来放数据时,我们将元素入队列放在数组尾,出队列时将数组前面元素出去后,会使前面浪费的空间越来越大。

基于此我们就用循环队列来实现,还是数组作为底层,但我们将其想象成一个圆。

2.2.2 接口实现

class MyCircularQueue {
	//构造器,设置队列长度为 k
    public 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() {}
};

2.2.3 成员变量

数组arr ,头下标front,尾节点下一个下标rear,数组长度size。

private int []arr;
private int front;
private int rear;
private int size;

2.2.4 构造器,设置队列长度为 k

因为我们使用的判空方法(下文讲)会造成一个空间的浪费,所以多申请一个空间。

public MyCircularQueue(int k) {
        size = k+1;
        arr = new int[size];
        front = rear = 0;
    }

2.2.5 向循环队列插入一个元素 成功插入则返回真

实现思路:

  1. 判断队列是否已满,满了就返回false。
  2. 不满就在rear放。
  3. 因为是循环队列,所以rear的赋值要使用取余。
public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }else{
            arr[rear] = value;
            rear = (rear + 1) % size;
            return true;
        }
    }

2.2.6 从循环队列中删除一个元素 成功删除则返回真

实现思路:

  1. 判断队列是否为空,空就返回false。
  2. 不空就直接将front指向下一个位置。
  3. 因为是循环队列,所以front的赋值要使用取余。
public boolean deQueue() {
        if(isEmpty()){
            return false;
        }else{
            front = (front + 1) % size;
            return true;
        }
    }

2.2.7 从队首获取元素。如果队列为空,返回 -1

实现思路:

  1. 先判断队列是否为空,为空返回-1。
  2. 不为空,返回front下标对应值。
public int Front() {
        if(isEmpty()){
            return -1;
        }else{
            return arr[front];
        }
    }

2.2.8 获取队尾元素。如果队列为空,返回 -1

实现思路:

  1. 先判断队列是否为空,为空返回-1。
  2. 不为空,再判断rear是否为0,是0就返回数组最后一个元素。
  3. 不为0,就直接返回rear-1下标对应的元素。
public int Rear() {
         if(isEmpty()){
            return -1;
        }else{
            if(rear == 0){
                return arr[size - 1];
            }else{
                return arr[rear - 1];
            }                    
        }
    }

2.2.9 检查循环队列是否为空

检查空根据循环队列的实现有两种方法:

  1. 使用usedSize记录队列元素个数,个数为0就是空。
  2. 空一个空间,如果front和rear相等那就是空。
public boolean isEmpty() {
        return rear == front;
    }

2.2.10 检查循环队列是否已满

检查满根据循环队列的实现有两种方法:

  1. 使用usedSize记录队列元素个数,个数和size相等就是满。
  2. 空一个空间,如果rear的下一个位置就是front那就是满。
public boolean isFull() {
        return front == (rear+1) % size;
    }

三、Java中的Queue

Java中Queue的底层是LinkedList实现的。

并且Queue只是一个接口,必须new对象LinkedList才能使用。

3.1 实现的接口

实现的接口如下:

3.2 常用方法

常用方法如下:

四、队列练习

用队列实现栈

用栈实现队列

设计循环队列

到此这篇关于Java数据结构之队列示例详解的文章就介绍到这了,更多相关Java数据结构队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring MVC 处理一个请求的流程

    Spring MVC 处理一个请求的流程

    Spring MVC是Spring系列框架中使用频率最高的部分。不管是Spring Boot还是传统的Spring项目,只要是Web项目都会使用到Spring MVC部分。因此程序员一定要熟练掌握MVC部分。本篇博客简要分析Spring MVC处理一个请求的流程。
    2021-02-02
  • SpringBoot的application.yml不生效问题及解决

    SpringBoot的application.yml不生效问题及解决

    这篇文章主要介绍了SpringBoot的application.yml不生效问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 关于Poi读取Excel引发内存溢出问题的解决方法

    关于Poi读取Excel引发内存溢出问题的解决方法

    这篇文章主要给大家介绍了关于Poi读取Excel引发内存溢出问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。
    2017-08-08
  • 关于maven pom文件配置加载lib下的jar包

    关于maven pom文件配置加载lib下的jar包

    在项目中引用放置在lib文件夹中的第三方jar包需要通过POM文件进行特定配置,虽然将依赖放置在公司的Maven私服是更好的做法,但如果遇到部署问题,可以利用maven-jar-plugin进行配置,Spring Boot项目可以通过特定设置来实现
    2024-09-09
  • 一文带你解读所有HashMap的面试题

    一文带你解读所有HashMap的面试题

    HashMap在面试的时候,是非常容易被问到的。因为在JDK8出来之后,非常容易被问到关于HashMap的知识点,而如果对于没有研究过他的源代码的同学来说,这个可能只是说出一部分来。本文就把HashMap上面大部分会被在面试中问到的内容,做个总结,希望有所帮助
    2022-09-09
  • Curator实现zookeeper的节点监听详解

    Curator实现zookeeper的节点监听详解

    这篇文章主要介绍了Curator实现zookeeper的节点监听详解,Curtor框架中一共有三个实现监听的方式,一种是NodeCache监听指定节点,一种是pathChildrenCache监听子节点,一种是TreeCache可以监控所有节点 相当于以上两种的合集,需要的朋友可以参考下
    2023-12-12
  • JavaWeb核心技术中Session与Cookie浅析

    JavaWeb核心技术中Session与Cookie浅析

    session的工作原理和cookie非常类似,在cookie中存放一个sessionID,真实的数据存放在服务器端,客户端每次发送请求的时候带上sessionID,服务端根据sessionID进行数据的响应
    2023-02-02
  • java 出现Zipexception 异常的解决办法

    java 出现Zipexception 异常的解决办法

    这篇文章主要介绍了java 出现Zipexception 异常的解决办法的相关资料,出现 java.util.zip.ZipException: error in opening zip file 异常的原因及解决方法,需要的朋友可以参考下
    2017-08-08
  • MyBatis多对多映射初识教程

    MyBatis多对多映射初识教程

    这篇文章重点给大家介绍mybatis多对多映射,多对多映射的例子也很常见,本文通过代码实例相结合的方式给大家介绍mybatis多对多映射,需要的朋友参考下吧
    2016-08-08
  • Java通过What、Why、How了解弱引用

    Java通过What、Why、How了解弱引用

    这篇文章主要介绍了Java通过What、Why、How了解弱引用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论