【数据结构】_队列经典算法OJ:循环队列

目录

[1. 题目描述及链接](#1. 题目描述及链接)

[2. 解题思路](#2. 解题思路)

[2.1 循环队列的设计](#2.1 循环队列的设计)

[2.2 关于循环队列的假溢出问题](#2.2 关于循环队列的假溢出问题)

[3. 程序](#3. 程序)

注:部分方法实现细节


1. 题目描述及链接

题目链接:622. 设计循环队列 - 力扣(LeetCode)

题目描述:

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为"环形缓冲器"。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

2. 解题思路

2.1 循环队列的设计

若采用数组作为队列底层结构,则需创建head标记数组第一个元素,tail标记数组最后一个元素的下一个位置,由于下标不具有循环特性,循环队列实现的麻烦之处在于下标超过k的下标处理问题,但获取队尾元素很方便;

若采用单链表作为队列底层结构,则需创建head指向链表第一个结点,tail指向链表最后一个结点,由于链表结点的链接关系,实现增删操作无需像数组结构一样需手动处理下标循环问题,但获取尾结点遍历等操作较为麻烦;

本题采用数组作为底层结构;

2.2 关于循环队列的假溢出问题

假设当前数组空间为4个数据大小,即k=4,依次进行以下操作:

解决方法:

方法1:增加有效数据存储的记录变量size

每插入一个元素则size++,每删除一个元素则size--,size=0表示队列为空,size=k表示队列满;

方法2:额外多开一个空间

3. 程序

cpp 复制代码
typedef struct {
    int* a;
    int head;  // 指向第一个数据
    int tail;  // 指向最后一个数据的下一个数据
    int k;
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->tail+1)%(obj->k+1) == obj->head;
}

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 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->tail==0?obj->a[obj->k]:obj->a[obj->tail-1];
        return obj->a[(obj->tail+obj->k)%(obj->k+1)];
    }
}


void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

注:部分方法实现细节

关于获取队尾元素的下标计算:

方式1:

cpp 复制代码
return obj->tail==0?obj->a[obj->k]:obj->a[obj->tail-1];

三目操作符特殊处理tail指向第一个数据位置:此时队列最后一个有效元素是ak

方式2:

cpp 复制代码
return obj->a[(obj->tail-1+obj->k+1)%(obj->k+1)];

对 tail-1 进行 +(k+1) 再模 (k+1) 的操作,使得tail=0时tail-1=-1的特殊情况得以统一处理,其中-1+1可抵消:

cpp 复制代码
return obj->a[(obj->tail+obj->k)%(obj->k+1)];
相关推荐
jarvisuni16 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
kobesdu17 小时前
流形上的优化:SO(3)与SE(3)的广义加减法在FAST-LIO中如何简化状态估计
人工智能·算法·fastlio
白狐_79817 小时前
408 数据结构算法题 01:线性表暴力求解保分指南
java·数据结构·算法
乐观勇敢坚强的老彭17 小时前
C++信奥:开关门、开关灯问题
开发语言·c++·算法
冻柠檬飞冰走茶17 小时前
PTA基础编程题目集 7-31 字符串循环左移(C语言实现)
c语言·开发语言·数据结构·算法
Hi李耶17 小时前
【LeetCode】4-寻找两个正序数组的中位数
算法·leetcode·职场和发展
图灵机z18 小时前
【算法提高课】AcWing 1027. 方格取数 长期攻克提高课-day3(3/219)
算法
hans汉斯18 小时前
计算机科学与应用|改进MeanShift算法在智能监控视频中的应用研究
图像处理·人工智能·功能测试·深度学习·算法·音视频
来一碗刘肉面18 小时前
树的存储结构
数据结构
一次旅行19 小时前
AutoAWQ完整实战:MIT激活感知AWQ量化,模型显存减半、推理提速且精度无损
人工智能·python·算法