06.队列

2020-05-23  本文已影响0人  学海一乌鸦

1.定义

一种操作受限的数据结构,只支持入列(enqueue)和出列(dequeue)

2.实现

用数组来实现

public class ArrayQueue {

    // 队列的长度
    private int len;
    // 队尾
    private int tail;
    // 队头
    private int head;
    // 数组
    int[] arr;

    public ArrayQueue(int len) {
        this.len = len;
        this.tail = 0;
        this.head = 0;
        arr = new int[len];
    }

    // 队列中加元素
    public boolean enqueue(int item) {
        if (tail == len) {
            // 说明队列已经满了
            if (head == 0) {
                return false;
            }
            // 搬移,将head-tail的元素搬迁到 0-(tail-head)
            for (int i = head; i < tail; i++) {
                arr[i - head] = arr[i];
            }
            // 更新搬移后的tail和head
            head = 0;
            tail = tail - head ;
        }
        arr[tail++] = item;
        return true;
    }

    // 出列也是从最后面先出
    public int dequeue() {
        // 如果二者相等,说明没有元素了
        if (head == tail) {
            return null;
        }
        int ret = arr[head];
        head++;
        return ret;
    }
}
image.png

用链表来实现

public class LinkedQueue {

    // 尾结点
    Node tailNode = null;
    // 头结点
    Node headNode = null;

    // 入队
    public boolean enqueue(int item) {
        if (tailNode == null) {
            headNode = tailNode = new Node(item, null);
        } else {
            tailNode.next = new Node(item, null);
            tailNode = tailNode.next;
        }
        return true;
    }

    // 出队
    public int dequeue() {
        if (headNode == null) {
            return null;
        }
        int ret = headNode.data;
        headNode = headNode.next;
        //注意更新一下tailhead
        if (headNode == null) {
            tailNode = null;
        }
        return ret;
    }

    class Node {
        private int data;
        private Node next;

        public Node(int data, Node next) {
            this.data = data;
            this.next = next;
        }
    }
}
image.png

循环队列


public class CircularQueue {
    // 初始数组,假定为int类型
    int[] arr;
    // 容量
    int size;
    // 头
    int head;
    // 尾
    int tail;

    // 初始化
    public CircularQueue(int size) {
        this.size = size;
        arr = new int[size];
        head = 0;
        tail = 0;
    }

    public boolean enQueue(int item) {
        // 队列已经满的标志
        if ((tail + 1) % size == head) {
            return false;
        }
        arr[tail] = item;
        // 对于tail增加要考虑
        tail = (tail + 1) % size;
        return true;
    }

    public int deQueue() {
        // 表示队列已经满
        if (tail == head) {
            return null;
        }
        int ret = arr[head];
        head = (head + 1) % size;
        return ret;
    }
}

3.用途

3.1 阻塞队列

在队列的基础上加了阻塞的操作,如果入队时候没有空余位置或者出队的时候没有元素,那么就阻塞等待。
利用此可以实现一个生产者-消费者模型:基于阻塞队列实现的“生产者 - 消费者模型”,可以有效地协调生产和消费的速度。当“生产者”生产数据的速度过快,“消费者”来不及消费时,存储数据的队列很快就会满了。这个时候,生产者就阻塞等待,直到“消费者”消费了数据,“生产者”才会被唤醒继续“生产”。


image.png

3.2并发队列

3.3 线程池设计

当我们向固定大小的线程池中请求一个线程时,如果线程池中没有空闲资源了,这个时候线程池如何处理这个请求?是拒绝请求还是排队请求?各种处理策略又是怎么实现的呢?

实际上,对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过“队列”这种数据结构来实现请求排队

4.小结

上一篇 下一篇

猜你喜欢

热点阅读