双端队列

队列
循环队列
双端队列

示例练习>>>

双端队列具有队列和栈两种数据结构的性质,在两边都能插入和删除,但不能在中间删除和插入,如下图所示。

我们前面讲的 双向链表 ,如果不在中间执行添加和删除操作的话,也可以把他看作是一个双端队列。双端队列的实现有两种方式,一种是使用链表,一种是使用数组,使用链表可以参考前面讲的 双向链表 ,这里我们来介绍使用数组的实现方式,如下图所示。

双端队列元素的添加:

双端队列元素的删除:

来看下代码:

public class Qeque<E> {

    private Object[] data;
    private final int maxSize;// 队列的最大容量。
    private int size; // 队列中元素的个数。
    private int head;// 队列不为空就存储头部元素的位置。
    private int tail;// 存储尾部元素的下一个应该存放的位置。

    public Qeque(int maxSize) {
        if (maxSize <= 0)
            throw new IllegalArgumentException("队列容量必须大于0 : " + maxSize);
        this.maxSize = maxSize;
        data = new Object[this.maxSize];
    }

    // 在头部添加元素。
    public void addHead(E val) {
        if (isFull())
            throw new IllegalStateException("队列已经满了,无法再加入……");
        head--;
        head = (head + maxSize) % maxSize;// 防止 head 出现 -1 。
        data[head] = val;
        size++;
    }

    // 在尾部添加元素。
    public void addTail(E val) {
        if (isFull())
            throw new IllegalStateException("队列已经满了,无法再加入……");
        data[tail++] = val;
        tail = tail % maxSize;
        size++;
    }

    // 删除头部元素
    public E removeHead() {
        if (isEmpty())
            throw new IllegalStateException("队列是空的,无法删除……");
        E result = (E) data[head];// 获取头部元素的值。
        data[head++] = null;// 头部元素清空,清空之后 head 指针往右移一步。
        head = head % maxSize;
        size--;
        return result;
    }

    // 删除尾部元素。
    public E removeTail() {
        if (isEmpty())
            throw new IllegalStateException("队列是空的,无法删除……");
        tail--;
        tail = (tail + maxSize) % maxSize;
        E result = (E) data[tail];
        data[tail] = null;
        size--;
        return result;
    }

    // 获取头部元素。
    public E getHead() {
        if (isEmpty())
            throw new NoSuchElementException();
        return (E) data[head];
    }

    // 获取尾部元素。
    public E getTail() {
        if (isEmpty())
            throw new NoSuchElementException();
        return (E) data[(tail - 1 + maxSize) % maxSize];
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public boolean isFull() {
        return size == maxSize;
    }

    public int size() {
        return size;
    }
}

参考:
ArrayDeque.java

相关链接

数组
数组滚动数组差分数组树状数组
链表
链单向表双向链表循环链表跳表异或链表
队列
队列循环队列双端队列
散列表
散列表
二叉树二叉搜索树AVL树红黑树字典树哈夫曼树线段树笛卡尔树
图的介绍图的遍历Dijkstra算法Bellman-Ford算法SPFA算法Floyd算法Prim算法Kruskal算法Boruvka算法拓扑排序

信奥赛编程(刷题请进)>>>

经过两年的打磨,我的新作《算法秘籍》已经出版,有需要的可以点击购买。也可以点击 内容介绍 查看详情。