一、概念与结构
循环队列是一种特殊的队列,首尾相连成环,也叫环形队列。环形队列具有以下三个特点:
(1)队头删除数据,队尾插入数据。
(2)给定固定的空间,使用过程中不能扩容。
(3)环形队列满了之后,不能继续插入数据(即插入数据失败)。
环形队列可以使用数组实现,也可以使用循环链表实现。使用数组实现的话更简单。定义头指针front和尾指针rear。当rear指向最后一个元素的时候,我们只需要让rear % 空间大小就可以让rear指针重新指向front。
但是,这样又带来一个问题,当环形队列为空时:front == rear;当环形队列满了:front == rear。那么,我们该如何区分环形队列是空还是满呢?我们可以在结构体中再定义一个size变量,用于统计环形队列中有效数据的个数。但是这样又要额外开辟四个字节的空间,有没有更好的办法呢?我们额外申请一块空间,但这块空间不保存任何数据,这样就不用额外增加结构体的成员变量。
此时,rear == front表示环形队列为空;如果满足(rear + 1)%(k + 1)== front,表示环形队列满了。
二、题目描述
https://leetcode.cn/problems/design-circular-queue
三、参考代码
typedef struct
{int* arr;int front;//队头int rear;//队尾int capacity;//循环队列的空间大小
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k)
{MyCircularQueue* pq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//申请k+1个空间pq->arr = (int*)malloc((k + 1) * sizeof(int));pq->front = pq->rear = 0;pq->capacity = k;return pq;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{return obj->front == obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj)
{return (obj->rear + 1) % (obj->capacity + 1) == obj->front;
}
//向循环队列中插入一个元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{//先判断是否满了if(myCircularQueueIsFull(obj)){return false;}//没有满else{obj->arr[obj->rear++] = value;obj->rear %= obj->capacity + 1;return true;}
}
//从循环队列中删除一个元素
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{if(myCircularQueueIsEmpty(obj)){return false;}//非空else{obj->front++;obj->front %= obj->capacity + 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 prev = obj->rear - 1;if(obj->rear == 0){prev = obj->capacity;}return obj->arr[prev];
}void myCircularQueueFree(MyCircularQueue* obj)
{if(obj->arr)free(obj->arr);obj->arr = NULL;obj->front = obj->rear = obj->capacity = 0;free(obj);obj = NULL;
}/*** Your MyCircularQueue struct will be instantiated and called as such:* MyCircularQueue* obj = myCircularQueueCreate(k);* bool param_1 = myCircularQueueEnQueue(obj, value);* bool param_2 = myCircularQueueDeQueue(obj);* int param_3 = myCircularQueueFront(obj);* int param_4 = myCircularQueueRear(obj);* bool param_5 = myCircularQueueIsEmpty(obj);* bool param_6 = myCircularQueueIsFull(obj);* myCircularQueueFree(obj);
*/