定义
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
优点
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
循环队列的属性
buff:一个固定大小的数组,用于保存循环队列的元素。
size:循环队列的容量,即队列中最多可以容纳的元素数量。
r:队列首元素对应的数组的索引。读指针,指向下一个被读的位置。
w:队列尾元素对应的索引的下一个索引。写指针,指向下一个被写的位置。
检测队列是否为空

当读指针等于写指针时,r == w,表示队列为空
bool myCircularQueueIsEmpty(MyCircularQueue *obj)
{
return obj->w == obj->r;
}
检测队列是否已满

当写指针的下一个位置是读指针时,表示队列已经满了,w+1 == r

w + 1 会大于 size,需要对 w + 1 取 size 余 , w + 1 % size == r
bool myCircularQueueIsFull(MyCircularQueue *obj)
{
return (obj->w + 1) % obj->size == obj->r;
}
初始化队列

读写指针初始化为0
MyCircularQueue *myCircularQueueCreate(int k)
{
MyCircularQueue *obj = (MyCircularQueue *)malloc(sizeof(MyCircularQueue));
obj->size = k + 1;
obj->w = obj->r = 0;
obj->buff = (int *)malloc(sizeof(int) * obj->size);
return obj;
}
在队列的尾部插入一个元素


写完后,写指针移动到下一个需要写的位置 w = w + 1


w 会大于 size,需要对 w + 1 取 size 余 ,w = w + 1 % size
bool myCircularQueueEnQueue(MyCircularQueue *obj, int value)
{
if (myCircularQueueIsFull())
return false;
obj->buff[obj->w] = value;
obj->w = (obj->w + 1) % obj->size;
return true;
}
先判断队列是否已满,如果满了直接返回false
从队首取出一个元素


读完后,读指针移动到下一个需要读的位置 r = r + 1

r 会大于 size,需要对 r + 1 取 size 余 ,r = r + 1 % size
bool myCircularQueueDeQueue(MyCircularQueue *obj)
{
if (myCircularQueueIsEmpty(obj))
return false;
obj->r = (obj->r + 1) % obj->size;
return true;
}
先判断队列是否已空,如果空了直接返回false
返回队首的元素
先判断队列是否已空,如果空了直接返回 -1
int myCircularQueueFront(MyCircularQueue *obj)
{
if (myCircularQueueIsEmpty(obj))
return -1;
return obj->buff[obj->r];
}
返回队尾的元素
先判断队列是否已空,如果空了直接返回 -1
int myCircularQueueRear(MyCircularQueue *obj)
{
if (myCircularQueueIsEmpty(obj))
return -1;
return obj->buff[(obj->w - 1 + obj->size) % obj->size];
}
释放内存
void myCircularQueueFree(MyCircularQueue *obj)
{
free(obj->buff);
free(obj);
}
示例
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct
{
int r;
int w;
int size;
int *buff;
} MyCircularQueue;
bool myCircularQueueIsFull(MyCircularQueue *obj);
bool myCircularQueueIsEmpty(MyCircularQueue *obj);
/**
* @brief 初始化队列
*
* @param k 队列大小
* @return MyCircularQueue*
*/
MyCircularQueue *myCircularQueueCreate(int k)
{
MyCircularQueue *obj = (MyCircularQueue *)malloc(sizeof(MyCircularQueue));
obj->size = k + 1;
obj->w = obj->r = 0;
obj->buff = (int *)malloc(sizeof(int) * obj->size);
return obj;
}
/**
* @brief 在队列的尾部插入一个元素
*
* @param obj
* @param value 数值
* @return true
* @return false
*/
bool myCircularQueueEnQueue(MyCircularQueue *obj, int value)
{
if (myCircularQueueIsFull(obj))
return false;
obj->buff[obj->w] = value;
obj->w = (obj->w + 1) % obj->size;
return true;
}
/**
* @brief 从队首取出一个元素
*
* @param obj
* @return true
* @return false
*/
bool myCircularQueueDeQueue(MyCircularQueue *obj)
{
// if (obj->w == obj->r)
// {
// return false;
// }
if (myCircularQueueIsEmpty(obj))
return false;
obj->r = (obj->r + 1) % obj->size;
return true;
}
/**
* @brief 返回队首的元素
*
* @param obj
* @return int
*/
int myCircularQueueFront(MyCircularQueue *obj)
{
if (myCircularQueueIsEmpty(obj))
return -1;
return obj->buff[obj->r];
}
/**
* @brief 返回队尾的元素
*
* @param obj
* @return int
*/
int myCircularQueueRear(MyCircularQueue *obj)
{
if (myCircularQueueIsEmpty(obj))
return -1;
return obj->buff[(obj->w - 1 + obj->size) % obj->size];
}
/**
* @brief 检测队列是否为空
*
* @param obj
* @return true
* @return false
*/
bool myCircularQueueIsEmpty(MyCircularQueue *obj)
{
return obj->w == obj->r;
}
/**
* @brief 检测队列是否已满
*
* @param obj
* @return true
* @return false
*/
bool myCircularQueueIsFull(MyCircularQueue *obj)
{
return (obj->w + 1) % obj->size == obj->r;
}
/**
* @brief 释放内存
*
* @param obj
*/
void myCircularQueueFree(MyCircularQueue *obj)
{
free(obj->buff);
free(obj);
}
/**
* @brief 打印队列
*
* @param obj
*/
void print_circular_queue_data(MyCircularQueue *obj)
{
if (obj == NULL)
{
printf("Queue is NULL\n");
return;
}
int r = obj->r;
int w = obj->w;
int size = obj->size;
printf("队列: ");
for (int i = 0; i < size; ++i)
{
int current_index = (r + i) % size;
printf("%d ", obj->buff[current_index]);
}
printf("\n");
}
int main(void)
{
MyCircularQueue *obj = myCircularQueueCreate(3);
if (myCircularQueueEnQueue(obj, 1))
printf("插入 1\n");
if (myCircularQueueEnQueue(obj, 2))
printf("插入 2\n");
if (myCircularQueueEnQueue(obj, 3))
printf("插入 3\n");
if (!myCircularQueueEnQueue(obj, 4))
printf("队列已满\n");
printf("队尾元素是 %d\n", myCircularQueueRear(obj));
if (myCircularQueueIsFull(obj))
printf("队列为满\n");
if (myCircularQueueDeQueue(obj))
printf("取出队首\n");
if (myCircularQueueEnQueue(obj, 4))
printf("插入 4\n");
printf("队尾元素是 %d\n", myCircularQueueRear(obj));
return 0;
}

2611

被折叠的 条评论
为什么被折叠?



