java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java 队列queue

Java 队列Queue从原理到实战指南

作者:Dylan的码园

本文介绍了Java中队列(Queue)的底层实现、常见方法及其区别,通过LinkedList和ArrayDeque的实现,以及循环队列的概念,展示了如何高效地进行元素的入队、出队和查看操作,感兴趣的朋友跟随小编一起看看吧

一、队列的认识

队列的底层与集合框架

在 Java 中,队列(Queue)是集合框架的一部分,属于 java.util 包下的接口。

从底层实现来看,不同的队列实现类底层数据结构不同。但是主要是由链表和数组实现的.
LinkedList 实现了 Queue 接口,它底层基于双向链表,通过节点的链接来维护队列的先进先出(FIFO)特性,插入和删除元素时效率较高.
ArrayDeque 则底层基于数组,利用数组的索引操作来模拟队列,在首尾操作元素时也能有较好的性能。

集合框架为队列提供了统一的接口规范,让开发者能方便地使用队列的各种操作,如入队(offer)、出队(poll)、查看队首元素(peek)等,同时也能结合集合框架中的其他类和接口,实现更复杂的数据结构和算法操作。

java集合框架

常见的队列方法

插入元素方法对比(add和offer)

移除元素方法对比(remove和poll)

查看队首元素方法对比(element和peek)

简单说就是

二、方法简单实现

Linkedlist实现

public class MyQueue {
    // 使用LinkedList实现的队列,存储整数类型元素
    // LinkedList实现了Queue接口,提供了队列的基本操作 向上转型
    Queue<Integer> queue = new LinkedList<>();
    //静态内部类
    static class ListNode{
        public int val;
        public ListNode prev; //链表中的两个重要指向
        public ListNode next;
        public ListNode(int val){
            //构造方法 用于实例化对象
            this.val = val;
        }
    }
    public ListNode first;
    public ListNode last;
}
  public boolean isEmpty(){
        return first ==  null && last ==null;
    }
    public int size(){
        int count = 0;
        ListNode cur = first;
        while (cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }
public void offer(int val){
        ListNode node = new ListNode(val);
        if (isEmpty()){
           first = last = node;
        }else {
           last.next = node;
           node.prev = last;
           last = node;
        }
    }
public int poll(){
        int val = first.val;
        if (isEmpty()){
            return -1;
        }
        if (first == last){
            first = null;
            last = null;
        }else {
            first = first.next;
            first.prev = null;
        }
        return val;
    }
public int pop(){
        if (isEmpty()){
            return -1;
        }
        else {
            return first.val;
        }
    }

数组实现遇到的问题

三、引入循环队列

两个问题

从上面的图可以看出有两个棘手的问题

如何正确表示下边(从尾部到头部)?

公式法
(r + 偏移量) % len
(f + 偏移量) % len

如何判断队列满不满?

标记法
在rear = front (起始时) tip = !isFull标记一下,当下一次出现rear = front时, tip = isFull.不再进行插入

预留空间法
在循环队列中让rear的下一位就是front,即(rear+1)%len = front

预留空间法实现

代码示例

public class MyCircularQueue {
    //预留空间法
    //初始变量的定义
    public int [] elem;
    public int rear ;
    public int front;
    //构造方法进行初始化
    public MyCircularQueue(int k){
        this.elem = new int [k];
    }
    /****
     * 入队
     */
    public boolean enQueue(int val) {
        //判满
        if (isFull()) {
            return false;
        }
        elem[rear] = val;
        rear = (rear + 1) % elem.length;
        return true;
    }
    //出队
    public boolean deQueue (){
        if (isEmpty()){
            return false;
        }
        front = (front+1)%elem.length;
        return true;
    }
    /****
     * 返回头
     * @return
     */
    public int getFront(){
        if (isEmpty()){
            return -1;
        }
        return elem[front];
    }
    /****
     * 返回尾
     * @return
     */
    public int getRear(){
        if (isEmpty()){
            return -1;
        }
        if (rear == 0)
            return elem[elem.length-1];
                    //处理边界问题
        }else {
            return elem[rear-1];
        }
    }
    public boolean isFull(){
        //r的下一个是f
        return (rear+1)%elem.length == front;
    }
    public boolean isEmpty(){
        return front == rear;
    }
}

标记法实现

代码示例

public class MyCircularQueue {
    //标记法
    //初始变量的定义
    public int [] elem;
    public int rear ;
    public int front;
    //构造方法进行初始化
    public MyCircularQueue(int k){
        this.elem = new int [k];
    }
	private boolean isFull0 = false;
    public boolean isFull2(){
        //r的下一个是f
        return isFull0;
    }
    public boolean isEmpty2(){
        return front == rear && !isFull0;
        }
    //标记法
    public boolean enQueue2(int val) {
        //判满
        if (isFull2()) { //一开始进不来
            return false;
        }
        elem[rear] = val;
        rear = (rear + 1) % elem.length;
        //入队后判断是不是满了
        if (rear == front) {
            isFull0 = true;
        }
        return true;
    }
    //出队
    public boolean deQueue2 (){
        if (isEmpty()){
            return false;
        }
        front = (front+1)%elem.length;
        isFull0 = false;
        return true;
    }
}

四、实战应用(见<历练场>)

队列实现栈

栈实现队列

总结

好啦,到这里我们队列的知识就分享到这里了,谢谢大家的阅读。如有问题请直接指出。

到此这篇关于Java 队列Queue从原理到实战指南的文章就介绍到这了,更多相关java 队列queue内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文