这是Leetcode中的第622题,大家可以做一下:
622.设计循环队列
一.解题思路:
1.循环?怎么循环呢?
2.为何要多开一个空间?
初始状态我们将front和rear都设置为0,此时队列为空
那么可能很多小伙伴会仍然像非循环队列那样让front指向队首元素,rear指向队尾元素的下一个,
入队列:arr[rear]=value;rear++;
出队列:front++;
也就是这样:
中间过程图:此时0,1,2,3,4进入队列
最终状态
图中0,1,2,3,4,5,6,7依次进入队列,正好也表示数组的下标
此时队列满了,不过:front=rear
此时front=rear,本该表示队列为空,但是现在队列是满的,那我们应该如何解决这个问题呢?
常见的方法有两种:
1.留一个空位, front和rear重合为空,front在rear前面一个位置为满
2.用一个变量记录队列中元素数量
这里我们采用第一种方法:
3.怎么判空,怎么判满?
判空:front==rear
判满:(rear+1)%(队列长度)==front
二:本题特殊之处
所以有了下面的代码:
//取队尾元素的函数
int myCircularQueueRear(MyCircularQueue* obj) {
//题目要求:如果队列为空,返回-1
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
//rear==0
if(obj->rear==0)
{
return obj->arr[obj->k];
}
//rear!=0
else
{
return obj->arr[obj->rear-1];
}
}
代码如下:
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
int ret_i=(obj->rear+obj->k)%(obj->k+1);
return obj->arr[ret_i];
}
三.本题代码(C语言实现)
typedef struct {
int* arr;
int front;
int rear;
int k;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
//两次malloc
MyCircularQueue* cq=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
cq->arr=(int*)malloc(sizeof(int)*(k+1));
cq->front=0;
cq->rear=0;
cq->k=k;
return cq;
}
//Front函数和Rear函数要判空和判满,前置声明一下
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->arr[obj->rear]=value;
obj->rear++;
//防止假溢出,实现循环,进行取余操作
obj->rear%=(obj->k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->front++;
//防止假溢出,实现循环,进行取余操作
obj->front%=(obj->k+1);
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
//队列为空
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->arr[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {
//队列为满
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
int ret_i=(obj->rear+obj->k)%(obj->k+1);
return obj->arr[ret_i];
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->rear;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->k+1)==obj->front;
}
void myCircularQueueFree(MyCircularQueue* obj) {
//两次free
free(obj->arr);
free(obj);
}
以上就是循环队列的讲解,希望能对大家有所帮助!