循环队列(C语言实现)

定义

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 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;
}

在这里插入图片描述

力扣官方题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值