【数据结构】队列-Queue

本文介绍了队列的基本概念、Java中的Queue接口及其使用方法,包括模拟实现的单向队列和循环队列,以及双端队列(Deque)的原理和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

⭐ 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:浅谈数据结构
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖


在这里插入图片描述

1.什么是队列

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

在这里插入图片描述

2. 队列的使用

在Java中,Queue是个接口,底层是通过链表实现的:
在这里插入图片描述

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检测队列是否为空

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

上述方法的实现:

import java.util.LinkedList;
import java.util.Queue;
public class Main {
    //方法的实现
    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());
        }
    }
}

3. 队列的模拟实现

我们知道队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过线性表可以了解到常见的空间类型有两种:顺序结构链式结构

在这里插入图片描述
模拟实现队列:

public class MyQueue {
    //双向链表节点
    static class ListNode {
        public int val;
        public ListNode next;
        public ListNode prev;

        public ListNode(int val) {
            this.val = val;
        }
    }

    public ListNode head;//队头
    public ListNode last;//队尾
    public int usedSize;//队列元素个数

    // 入队列---向双向链表位置插入新节点
    public boolean offer(int val) {
        ListNode node = new ListNode(val);
        if(head == null) {
            head = node;
            last = node;
        }else {
            last.next = node;
            node.prev = last;
            last = last.next;
        }
        usedSize++;
        return true;
    }

    // 出队列---将双向链表第一个节点删除掉
    // 1. 队列为空
    // 2. 队列中只有一个元素----链表中只有一个节点---直接删除
    // 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除
    public int poll() {
        if(head == null) {
            return -1;
        }
        int retVal = head.val;
        if(head.next == null) {
            head = null;
            last = null;
            return retVal;
        }
        head = head.next;
        head.prev = null;//第一个节点删除
        usedSize--;
        return retVal;
    }

    // 获取队头元素---获取链表中第一个节点的值域
    public int peek() {
        if(head == null) {
            return -1;
        }
        return head.val;
    }

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

    public int size() {
        return usedSize;

4. 循环队列

循环队列顾名思义就是首位相连的队列,自然界中的生产者消费者分解者模型可以使用循环队列来描述。而环形队列通常使用数组实现。
在这里插入图片描述
数组下标循环的小技巧

  1. 下标最后再往后(offset 小于 array.length): index = (index + offset) % array.length
    在这里插入图片描述
  2. 下标最前再往前(offset 小于 array.length): index = (index + array.length - offset) %array.length
    在这里插入图片描述

如何区分空与满?

  1. 通过添加 size 属性记录
  2. 保留一个位置
  3. 使用标记
    在这里插入图片描述

循环队列的实现:

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 == 0) ? elem.length-1 : rear-1;
        return elem[index];
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public boolean isFull() {
        return (rear+1)%elem.length == front;
    }
}

5. 双端队列(Deque)

**双端队列(deque)**是指允许两端都可以进行入队和出队操作的队列。在这里插入图片描述
Deque是一个接口,使用时必须创建LinkedList的对象:

在这里插入图片描述
在实际工程中,使用Deque接口是比较多的,栈和队列均可以使用该接口:

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值