9.队列:生产者消费者模式 (2)

我们可以看到,图中这个队列的大小为 8,当前 head=4,tail=7。当有一个新的元素 a 入队时,我们放入下标为 7 的位置。但这个时候,我们并不把 tail 更新为 8,而是将其在环中后移一位,到下标为 0 的位置。当再有一个元素 b 入队时,我们将 b 放入下标为 0 的位置,然后 tail 加 1 更新为 1。所以,在 a,b 依次入队之后,循环队列中的元素就变成了下面的样子:

队列为空的判断依然是 front == rear,队列满的条件则是 (rear + 1) % capacity = front

你有没有发现,当队列满时,图中的 tail 指向的位置实际上是没有存储数据的。所以,循环队列会浪费一个数组的存储空间。

/** * 数组实现环形队列 * * @param <E> */ public class ArrayCircleQueue<E> extends AbstractQueue<E> { /** * The queued items */ final E[] items; /** * 队头指针 */ private int front; /** * 队尾指针 */ private int rear; public int capacity() { return items.length; } /** * Creates an ArrayQueue with the given capacity * * @param capacity the capacity of this queue */ public ArrayCircleQueue(Class<E> type, int capacity) { if (capacity <= 0) { throw new IllegalArgumentException(); } this.items = (E[]) Array.newInstance(type, capacity); } @Override public E dequeue() { if (front == rear) { throw new IllegalStateException("Queue empty"); } E item = items[front]; front = (front + 1) % items.length; return item; } @Override public boolean enqueue(E e) { checkNotNull(e); int newRear = (rear + 1) % items.length; if (newRear == front) { throw new IllegalStateException("Queue full"); } items[rear] = e; this.rear = newRear; return true; } @Override public boolean isFull() { return (rear + 1) % items.length == front; } @Override public boolean isEmpty() { return rear == front; } }

推荐阅读

1.

2.

3.

4.

5.

6.

7.

8.

原创不易,觉得有用希望随手「在看」「收藏」「转发」三连。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzdygs.html