携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
题目描述
设计一个循环队列,普通队列中一旦一个队列满了,即使队列的前面仍然有空间也不能继续插入元素。题目要求实现循环队列的构造以及取队头元素、取队尾元素、入队、出队、判断空、判断慢七个方法。
循环队列与普通队列的区别:
如下图一个初始化大小为6的普通队列,在进行enqueue(1)、enqueue(2)、enqueue(3)、enqueue(4)、dequeue()、dequeue()、dequeue()、enqueue(5)、enqueue(6)、enqueue(7),在最后入队元素7的时候因为队列已经满了,导致入队失败,即使当前队列前面的位置已经出队为空。
但循环队列可以利用队列前面已经出队元素位置的空间,如下图所示,在进行连续的三次出队后,队列的位置0、1、2三个位置为空,再进行连续入队三个元素后,队列位置0得到了重复的利用。
原题地址:622. 设计循环队列
解题思路
循环队列首先要解决的问题就是队头队尾的维护,这里我们采用变量front、taik来维护队头队尾所在的位置,front表示队头元素的位置,tail用来表示当前待插入的队尾位置。
其次要解决的问题就是怎么判断队列是否为空以及判断队列是否已满。很容易想到的就是利用front是否等于tail来判断,但当 时有两种情况,有可能是队列为空,有可能队列为满。分别对应下图中左右两种情况。
所以这里我们用flag变量表示上次操作是插入还是删除。如果上次的操作是插入且当前 ,则当前队列一定为满状态。如果上一次的操作是删除且当前 ,则当前队列一定为空状态。
实现代码
class MyCircularQueue {
public:
vector<int> queue;
// 维护队列的队头和队尾
int front,tail,size;
// 标记上一个操作是插入还是删除。false表示删除,true表示插入。
bool flag;
MyCircularQueue(int k) {
// 初始化队列的大小、队头队尾信息
queue = vector<int>(k);
front = 0,tail = 0,size = k;
flag = false;
}
bool enQueue(int value) {
// 如果当前队列为满,则插入失败
if(isFull()) return false;
// 标记上次的操作为插入
flag = true;
queue[tail] = value;
// 维护队尾信息
tail = (tail+1)%size;
return true;
}
bool deQueue() {
// 如果当前队列为空,则删除失败
if(isEmpty()) return false;
// 标记上次的操作为删除
flag = false;
// 维护队头信息
front = (front+1)%size;
return true;
}
int Front() {
// 如果当前队列为空,获取队头失败
if(isEmpty()) return -1;
return queue[front];
}
int Rear() {
// 如果当前队列为空,获取队尾失败
if(isEmpty()) return -1;
return queue[(tail-1+size)%size];
}
bool isEmpty() {
if(front == tail && !flag) return true;
return false;
}
bool isFull() {
if(front==tail && flag) return true;
return false;
}
};