目录
- 1、题目展示
- 2、问题分析
- 3、完整代码展示
- 4、结语
1、题目展示
在拿到题目时,通过分析我们知道,环形队列是一个有用固定位置数的队列,若队列已满就不能再向其中插入数据,且队列为循环,及队列的尾部的下一个为队列的头部。
在这种前提条件下,我们会联想到可以使用链表的形式进行实现,但是在使用链表创建队列时,需要开辟出题目要求数量的节点,并将其连接起来,十分麻烦,且在进行删除插入操作时会有对指针的操作,容易出现bug,故本文仅对如何使用数组来实现循环队列进行讲解。
2、问题分析
当使用数组来实现队列时,我们可以先假设题目要求创建四个空间存储空间的循环队列,示意图如下:
在创建好数组之后我们又如何让其可以循环呢,可以思考,当指向下标的位置越过了数组限制下标3时,我们让他取模,并回归到数组的0下标,或者也可以设置一个size来记录数组内数据的个数,并通过size来进行循环。
可循环的问题解决了,那我们如何判断循环队列中的空间是否满了或者空呢,我们可以设置两个数分别为head和tail,让其指向数组的首元素下标,即开始时head和tail都为0,当head和tail相等时,就判断它时空的循环队列。
可这时问题又出现了,当我们队列里存满了数据时,head也和tail相等,这就造成了很明显的bug,无法判断是相等还是空,这时我们可以在创建数组时多创建一个空间,比如说我们需要四个空间,在创建时就创建五个空间,但是数组里最多只存储四个数据,即总有一个空间是不存储数据的,这样就完美的解决了假溢出的问题。示意图如下:
此时我们假设进行两步操作,第一次向循环队列中插入四个数据,第二次删除四个数据。示意图分别如下:
我们可以明显地发现当tail的下一个位置为head时,循环队列时满的状态,当tail等于head时,循环队列是空的状态。
至此我们便可以依据此种规律进行代码的书写。
3、完整代码展示
至于如何对越界的head和tail进行取模转换,是一个数学上的问题,再此不再做过多的详解,看官可通过数学知识自行解答,下面是完整代码展示:
typedef struct
{
int* a;
int head;
int tail;
int k;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*(k+1));
obj->head = 0;
obj->tail = 0;
obj->k = k;
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->head == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return (obj->tail + 1) % (obj->k + 1) == obj->head;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->tail] = value;
obj->tail++;
obj->tail %= (obj->k + 1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return false;
obj->head++;
obj->head %= obj->k + 1;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[(obj->tail + obj->k ) % (obj->k + 1)];
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->a);
free(obj);
}
4、结语
十分感谢您观看我的原创文章。
本文主要用于个人学习和知识分享,学习路漫漫,如有错误,感谢指正。
如需引用,注明地址。