设计循环队列
题目
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环
队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
- MyCircularQueue(k): 构造器,设置队列长度为 k 。
- Front: 从队首获取元素。如果队列为空,返回 -1 。
- Rear: 获取队尾元素。如果队列为空,返回 -1 。
- enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
- deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
- isEmpty(): 检查循环队列是否为空。
- isFull(): 检查循环队列是否已满。
循环队列
普通队列内部使用数组实现,循环队列不同于普通队列,普通队列中数据索引移动到array.length
时,则数组使用完毕。
循环队列内当数组索引移动到最后一位时,会重新回到开头0
,如果队列未满,则可以继续使用。
实现设计思路
- 使用数组保存数据,初始化数组,数组大小为队列容量。
- 使用两个索引,因为数组循环使用,使用一个索引无法定位到队列头部和尾部。两个索引为
head
和tail
用于保存队列头部和尾部。 - 出队
deQueue()
时,如果队列不为空,head++
后移一位,入队enQueue(value)
时,如果队列未满,tail++
后移一位并赋值。 - 当
head
和tail
索引值为array.length
,说明已经超出数组范围,则回到数组起始位置0,使用取余的方法来实现,即(head+1) % array.length
和(tail+1) % array.length
。 head
初始值为0,tail
初始值为-1,只有入队后才能出队,所以当array[0]
已经被赋值后,才会第一次出队,head
才会移动,所以head=0
。初始化时队列为空,尾部没有值,所以tail=-1
- 使用变量
size
来维护队列数量,当入队时size++
,出队时size--
,size==0
时队列为空,size==array.length
时队列已满。 head
和tail
指向队头和队尾,所以array[head]
和array[tail]
对应的值。
实现代码
package com.newler.leetcode.queue;
import com.newler.leetcode.data.ListNode;
import java.util.LinkedHashMap;
import java.util.LinkedList;
class MyCircularQueue {
@[TOC](这里写自定义目录标题)private int[] circularQueue;
private int head, tail;
private int size = 0;
public MyCircularQueue(int k) {
circularQueue = new int[k];
head = 0;
tail = -1;
}
public boolean enQueue(int value) {
if (isFull()) {
return false;
}
tail = (tail+1)%circularQueue.length;
circularQueue[tail] = value;
size++;
return true;
}
public boolean deQueue() {
if (isEmpty()) {
return false;
}
head = (head+1) % circularQueue.length;
size--;
return true;
}
public int Front() {
if (isEmpty()) return -1;
return circularQueue[head];
}
public int Rear() {
if (isEmpty()) return -1;
return circularQueue[tail];
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == circularQueue.length;
}
}