🎬 鸽芷咕:个人主页 🔥 个人专栏:《Linux深造日志》《C++干货基地》
⛺️生活的理想,就是为了理想的生活!
🌈hello! 各位宝子们大家好啊,今天给大家带来循环队列的详细解析,队列我们会写了那么循环队列呢?今天这个还是有点难度的 ⛳️学完之后保证你对队列又会有一个更清晰的认识。让你彻底拿捏队列循环队列一搞完我们的队列学习就告一段落了。 📚本期文章收录在《数据结构&算法》,大家有兴趣可以看看呐! ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!
队列我们都自动是数据结构中类似排队一样的结构,主要满足:先进先出的特点。而循环队列的话顾名思义就是把头和尾链接起来循环这样就是循环队列了。
上面是为了方便大家理解而做的图,而实际的循环队列是这样的
这里我们先看一下力扣上面的题目要求我们,要实现循环队列要实现的功能然后再进行逐个实现就好了。
首先我们需要考虑的就是循环队列的结构,很多人可就会想到使用链表去实现循环队列但是这里有俩个问题:
rear
指向有数据的那么插入第一个数据的时候是否为空?rear
指向数据后面的空间那么 尾元素该如何去找?rear
满了如何判定是否为空所以为了解决这种情况我们选择试用数组的方式实现,多开一个元素来实现循环链表就完美解决问题了:
下标访问
解决找不到前一个元素的问题好了上面我们已经知道了循环队列用哪种方式更优,那么接下来就是设计循环队列的结构了:
📚 代码演示:
ypedef struct {
int* a;
int front;
int rear;
int k;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*(k+1));
obj->front = obj->rear = 0;
obj->k = k;
return obj;
}
这个就更加简单我们我们前面说了:
📚 代码演示:
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front == obj->rear;
}
如何检查队列是否满了,就需要判断一下 rear
的下一个是否为 front
了:
模除
一下就好了📚 代码演示:
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->k+1) == obj->front;
}
循环队列插入数据的话,首先要判断是否为满就然后插入就行了:
++obj->rear
了之后要考虑一下 rear
在最后一个位置的情况📚 代码演示:
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
{
return false;
}
else
{
obj->a[obj->rear] = value;
obj->rear++;
obj->rear %= (obj->k+1);
}
return true;
}
删除数据也是一样,循环队列如果空了就返回 false
没空 front++
就好了:
📚 代码演示:
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return false;
}
++obj->front;
obj->front %= (obj->k+1);
return true;
}
获取头元素就很简单啦,只需要使用 front
来当下标访问就好了
📚 代码演示:
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->front];
}
这里就需要考虑很多问题,rear是尾元素的下标的一个一个下标:
rear
指向中间怎么办? 如何回到上一个rear
下标为零的时候 如何回到他的上一个下标📚 代码演示:
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}
销毁就很简单了,先 free 掉我们动态开辟的空间,在free掉循环队列的空间就好了:
📚 代码演示:
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}
📚 代码演示:
typedef struct {
int* a;
int front;
int rear;
int k;
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front == obj->rear;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->k+1) == obj->front;
}
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*(k+1));
obj->front = obj->rear = 0;
obj->k = k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
{
return false;
}
else
{
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;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}
这里我们可以去力扣一下检验和练习一下:
☁️ 把本章的内容全部掌握,铁汁们对于队列的理解就更上一层楼了!
看到这里了还不给博主扣个:
⛳️ 点赞
☀️收藏
⭐️ 关注
!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。