zoukankan      html  css  js  c++  java
  • 线性表结构:队列

    什么是队列

    队列是一种先进入的元素先出的线性表结构。这个特性正好和栈的特性相反。

    我们知道,栈只支持两个基本操作:入栈 push()和出栈 pop()。队列跟栈非常相似,支持的操作也很有限,最基本的操作也是两个:入队 enqueue(),放一个数据到队列尾部;出队 dequeue(),从队列头部取一个元素。

    img

    手动实现队列

    队列的实现方式也有两种,一种是通过数组实现,叫顺序队列,另外一种是通过链表实现,叫链式队列。

    顺序队列

    public static class MyQueue<E> {
    
            private Object[] array;
            private int head;
            private int tail;
    
            public MyQueue(int capacity) {
                this.array = new Object[capacity];
            }
    
            public boolean enqueue(E e) {
                array[tail] = e;
                int length = array.length;
                tail = (++tail) % length;
                if (tail == head) {
                    // 扩容
                    Object[] data = new Object[length * 2];
                    int index = 0;
                    int i = head;
                    do {
                        data[index++] = array[i];
                        i = (++i) % length;
                    } while (i != head);
                    tail = length;
                    head = 0;
                    array = data;
                }
                return true;
            }
    
            public E dequeue() {
                if (head == tail) {
                    return null;
                }
                E item = (E) array[head];
                array[head] = null;
                head = (++head) % (array.length);
                return item;
            }
    
        }
    

    链式队列

     public static class MyQueue<E> {
    
            private Node head;
            private Node tail;
    
            public MyQueue() {
    
            }
    
            public MyQueue(E data) {
                head = tail = new Node(data);
            }
    
            public boolean enqueue(E data) {
                if (head == null) {
                    this.head = new Node(data);
                    this.tail = head;
                } else {
                    Node node = new Node(data);
                    tail.next = node;
                    tail = node;
                }
                return true;
            }
    
            public E dequeue() {
                if (head == null) {
                    return null;
                } else {
                    E item = (E) head.data;
                    head = head.next;
                    return item;
                }
            }
    
        }
    
    
        public static class Node<E> {
            private E data;
            private Node next;
    
            public Node(E data) {
                this.data = data;
                this.next = null;
            }
    
            public Node(E data, Node next) {
                this.data = data;
                this.next = next;
            }
        }
    

    JDK 中的队列实现

    如果不想自己实现队列,那么我们可以使用 JDK 提供的队列实现。

    img

    主要实现有:

    • ArrayDeque
    • LinkedList

    下面看下使用LinkedList来实现Queue的例子:

    public static class MyQueue<E> {
    
        private LinkedList<E> queue;
    
        public MyQueue() {
            this.queue = new LinkedList<E>();
        }
    
        public MyQueue(E e) {
            this.queue = new LinkedList<E>();
            queue.add(e);
        }
    
        public boolean enqueue(E e) {
            queue.offer(e);
            return true;
        }
    
        public E dequeue() {
            if (queue.isEmpty()) {
                return null;
            } else {
                return queue.pop();
            }
        }
    }
    

    常见的队列种类

    循环队列、阻塞队列、并发队列。它们在很多偏底层系统、框架、中间件的开发中,起着关键性的作用。比如高性能队列 Disruptor、Linux 环形缓存,都用到了循环并发队列;Java concurrent 并发包利用 ArrayBlockingQueue 来实现公平锁等。

    循环队列

    在上面的顺序队列的实现过程中,我们使用了循环队列的实现方式。使用循环队列,可以避免在数组中对数据进行搬移。

    阻塞队列

    所谓阻塞队列是指:在队列是空的情况下从队列头部取一个元素,操作会被阻塞直到队列中被插入一个元素,在队列满的情况下,向队列中插入一个元素,操作也会被阻塞,直到其他操作从队列中取出一个元素为止。

    我们发现,通过阻塞队列可以很好的实现一个生产者和消费者模式。

    - ArrayBlockingQueue.java
    - BlockingDeque.java
    - DelayQueue.java
    - LinkedBlockingDeque.java
    - LinkedBlockingQueue.java
    - LinkedTransferQueue.java
    - PriorityBlockingQueue.java
    - ScheduledThreadPoolExecutor
    - SynchronousQueue.java
    - TransferQueue.java
    

    Java 中提供了以上的阻塞队列相关的实现或者接口,其中的队列实现也是线程安全的。

    并发队列

    线程安全的队列实现,参考Java并发包下面的队列实现。

    队列的应用场景

    队列可以应用在任何有限资源池中,用于排队请求,比如数据库连接池等。实际上,对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过“队列”这种数据结构来实现请求排队。

    人生的主旋律其实是苦难,快乐才是稀缺资源。在困难中寻找快乐,才显得珍贵~
  • 相关阅读:
    Codeforces Round #344 (Div. 2) C. Report 其他
    Codeforces Round #344 (Div. 2) B. Print Check 水题
    Codeforces Round #344 (Div. 2) A. Interview 水题
    8VC Venture Cup 2016
    CDOJ 1280 772002画马尾 每周一题 div1 矩阵快速幂 中二版
    CDOJ 1280 772002画马尾 每周一题 div1 矩阵快速幂
    CDOJ 1279 班委选举 每周一题 div2 暴力
    每周算法讲堂 快速幂
    8VC Venture Cup 2016
    Educational Codeforces Round 9 F. Magic Matrix 最小生成树
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/14831231.html
Copyright © 2011-2022 走看看