目录
提前说明
文章基于LeetCode的题目,并不是完整的循环列表,只涉及其中部分功能,循环队列的完整代码请移步其他文章,本文只实现部分功能。
一、循环队列的定义
定义:循环队列属于队列的一种,具有队列的功能,可以在头尾进行插入和删除,因为可以改变头尾指针的位置,所以具有在任意节点操作的功能。
特点:
1.循环队列允许元素在队尾插入,在队头删除,同时遵循先进先出的原则。
2.笔者推荐使用数组实现循环队列,数组相比链表节约了找尾这一步骤,更加方便的快速访问,同时循环队列用数组实现可以不用移动数组内的元素。
3.在大量添加和删除元素时,循环队列相比链表更有效率,因为它不需要频繁移动指针寻找元素。
4.缺陷:不支持随机访问,不能像数组一样直接访问特定位置的元素。比如不能实现二分查找。
一般情况循环队列:
下面是正确的满循环队列
循环队列设计的解释:
循环队列为空时,rear==front,在同一位置;循环队列为满时,按一般情况走下去rear==front。
队列满和空的条件居然一样!这就会出现问题,队列是满是空程序无法判断。
为了针对这样的情况,需要设计出一个空位置,不放任何元素,类比做哨兵卫,通过取%的方式判断队列排满。
二、循环队列的接口功能
1.初始化:创造一个空的队列,底层是数组,头和尾指针指向同一节点,队列设置为空。
2.入队列:向循环队列插入一个元素。如果成功插入则返回真。
3.出队列:从循环队列中删除一个元素。如果成功删除则返回真。
4.查看队首:从队首获取元素。如果队列为空,返回 -1。
5.查看队尾:获取队尾元素。如果队列为空,返回 -1 。
6.验空:检查循环队列是否为空。
7.判满:检查循环队列是否已满。
8. 销毁:销毁开辟的数组。
三、循环队列的实现
1.循环队列的定义
typedef struct {
int* _a;//数组指针
int _front;
int _rear;
int _k;//记录数组长度
} MyCircularQueue;
2.初始化数据
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* p=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
p->_a=(int*)malloc(sizeof(int)*(k+1));
p->_front=0;
p->_rear=0;
p->_k=k;
return p;
}
3.入队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))//检验队列是否为满
{
return false;
}
obj->_a[obj->_rear]=value;
obj->_rear++;
obj->_rear %= (obj->_k+1);
return true;
}
解释obj->_rear %= (obj->_k+1):_rear遇到以下情况时需要取%
当队列满时直接返回错误;队列不满,头指针在原地,rear取%不影响,头指针不在原地,rear取%返回头。
4.出队列
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->_front++;
obj->_front %=(obj->_k+1);
return true;
解释:_front向后移动直接舍弃要删除的元素,与rear取%原理相同,同样都是返回原地
5.查看队首
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->_a[obj->_front];
}
6.查看队尾
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
else
{
int tail=obj->_rear-1;
if(tail==-1)
{
tail=obj->_k;
}
return obj->_a[tail];
}
}
解释:tail为_数组下标,当rear有如下情况时
tail的值会变为-1,因此需要将k重新赋值给tail,以免发生越组访问。
7.验空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->_front==obj->_rear;
}
8.判满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->_rear+1)%(obj->_k+1)==obj->_front;
}
9.销毁
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->_a);
free(obj);
}
四、完整代码
typedef struct {
int* _a;//数组指针
int _front;
int _rear;
int _k;//记录数组长度
} MyCircularQueue;
//初始化数据
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* p=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
p->_a=(int*)malloc(sizeof(int)*(k+1));
p->_front=0;
p->_rear=0;
p->_k=k;
return p;
}
//声明
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
//向循环队列插入一个元素。如果成功插入则返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->_a[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;
}
//从队首获取元素。如果队列为空,返回 -1
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->_a[obj->_front];
}
//获取队尾元素。如果队列为空,返回 -1
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
else
{
int tail=obj->_rear-1;
if(tail==-1)
{
tail=obj->_k;
}
return obj->_a[tail];
}
}
//检查循环队列是否为空
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(obj->_a);
free(obj);
}
/**
* 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);
*/