前言
- 当想要按顺序处理元素时,使用队列可能是一个很好的选择。
- 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
- 本文分别循环队列的设计和使用内置队列库及其常见操作。
- 为解决空间受限制队列出现的资源浪费,循环队列重用队列浪费的资源。
一、设计循环队列
循环队列的工作原理
在循环队列中,我们使用一个数组q和两个指针(head 和 tail)。 head 表示队列的起始位置,tail 表示队列的结束位置,数组q长度为len,入队元素为value。
- 队列为空: head =-1, tail = -1
- 队列为满:(tail - head + 1 = len) && (tail + 1 = head)
- 入队:
1)未满时才能入队
2)为空时入队,head = 0, tail = 0, q[tail] = value;
3)不为空且未满入队,tail ++,q[tail] = value;
4)不为空且未满,tail到达数组最后一个下标,即tail + 1 = len,则tail = 0 - 出队:
1)非空时才能出队
2)队列只剩最后一个元素,即head == tail时,head = -1,tail = -1
3)队列非空,head++;
4)队列非空,head到数组最后一个下标,即head + 1 = len,则 head = 0 - 取头元素:q[head]
- 取尾元素:q[tail]
标注:上述方法未使用mod。
若使用:
在非空非满时入队可用tail = (tail + 1) % len,q[tail] = value;
在非空且没有只剩下一个元素时出队可用head = (head +1) % len;
代码
class MyCircularQueue {
private int[] circularQueue;
private int head = -1;
private int tail = -1;
private int len;
/** Initialize your data structure here. Set the size of the queue to be k. */
public MyCircularQueue(int k) {
this.circularQueue = new int[k];
this.len = k;
}
/** Insert an element into the circular queue. Return true if the operation is successful. */
public boolean enQueue(int value) {
if(isEmpty()==true) {
this.head = 0;
this.tail = 0;
this.circularQueue[this.head] = value;
}
else if (isFull()==true) {
return false;
}
else {
if(this.tail == this.len - 1) {
this.tail = 0;
this.circularQueue[this.tail] = value;
}
else {
this.tail += 1;
this.circularQueue[this.tail] = value;
}
}
return true;
}
/** Delete an element from the circular queue. Return true if the operation is successful. */
public boolean deQueue() {
if (isEmpty() == true){
return false;
}
else {
if(this.head == this.tail){
this.head = -1;
this.tail = -1;
}
else if (this.head == this.len -1){
this.head = 0;
}
else {
this.head += 1;
}
}
return true;
}
/** Get the front item from the queue. */
public int Front() {
if (isEmpty()==true){
return -1;
}
int front = this.circularQueue[this.head];
return front;
}
/** Get the last item from the queue. */
public int Rear() {
if (isEmpty()==true){
return -1;
}
int rear = this.circularQueue[this.tail];
return rear;
}
/** Checks whether the circular queue is empty or not. */
public boolean isEmpty() {
if (this.head == -1 && this.tail == -1)
return true;
return false;
}
/** Checks whether the circular queue is full or not. */
public boolean isFull() {
if ((this.tail - this.head + 1 == this.len) || (this.tail + 1 == this.head) ){
return true;
}
return false;
}
二、内置队列库及其常见操作
常见操作
- 建立队列
Queue<Integer> q = new LinkedList();
- 入队
q.offer(value);
- 出队
q.poll();
- 去队列首元素
q.peak();
- 队列长度
q.size()
代码实例
引用了leetcode中的例子:
import java.util.Queue;
import java.util.LinkedList;
// "static void main" must be defined in a public class.
public class Main {
public static void main(String[] args) {
// 1. Initialize a queue.
Queue<Integer> q = new LinkedList();
// 2. Get the first element - return null if queue is empty.
System.out.println("The first element is: " + q.peek());
// 3. Push new element.
q.offer(5);
q.offer(13);
q.offer(8);
q.offer(6);
// 4. Pop an element.
q.poll();
// 5. Get the first element.
System.out.println("The first element is: " + q.peek());
// 7. Get the size of the queue.
System.out.println("The size is: " + q.size());
}
}