• 【数据结构】队列-Queue


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


    在这里插入图片描述

    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());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    5. 双端队列(Deque)

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

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

    Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
    Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现
    
    • 1
    • 2
  • 相关阅读:
    hdfs的一个运维小技巧
    持续部署Jenkins+Docker +Spring Cloud
    系列二、Lock接口
    Java集合框架
    类和对象·默认成员函数
    对话知名视觉艺术设计师走尺:只要用心 人人是插画师
    Qt元对象系统
    导航【Java设计模式】
    UDP-B-L-阿拉伯糖二钠盐,UDP-b-L-arabinopyranose disodium salt,15839-78-8
    Android数据对象序列化原理与应用
  • 原文地址:https://blog.csdn.net/iLoyo_/article/details/133905479