【队列】循环队列(Circular Queue)详解

【队列】循环队列(Circular Queue)详解

文章目录

一、循环队列简介

在实际开发中,队列是一种常用的数据结构,而循环队列(Circular Queue)则一般是一种基于数组实现的队列(也可使用循环链表)。与传统的 FIFO 队列相比,循环队列通过将数组首尾相连形成一个 “环”,能够更高效地利用内存空间。

循环队列的主要思想是:当队尾指针到达数组末端时,如果数组前面还有空余空间,就可以从数组头部重新利用这些空间进行入队操作。也就是说,数组的末端和头部通过逻辑上的连接,形成一个环状结构,从而避免了顺序队列中由于出队操作而导致的空间浪费问题。

如下图就是一个典型的循环队列,其中的 front 表示头指针,指向队头。rear 则表示尾指针,指向队尾元素的下一个位置。

请添加图片描述

二、循环队列的判空和判满

在循环队列中,frontrear 都是可以循环移动的,当队空时,front == rear 成立;当队满时,front == rear 也成立。因此显然不能只凭 front == rear 来判断队空还是队满。

为了解决这个问题,在循环队列中约定:少用一个元素空间,当队尾标识的 rear在队头标识front 的上一个位置时,队列为满。此时,判断队空和队满的条件分别如下:

队空时:front == rear

队满时:(rear + 1) % MAXSIZE == front

其中,MAXSIZE 是队列容量的大小

两种情况下队列中指针的状态如下图所示:

请添加图片描述

既然少一个元素空间,这就意味着,如果要存储的数据个数最大为 k,那么你需要开辟的循环队列的大小应为 k+1

三、循环队列的实现

我们来以具体的一道题目来实现循环队列的各种操作

leetcode 622. 设计循环队列

typedefstruct{int* a;int front;// 头“指针”指向队头数据int tail;// 尾“指针”指向队尾的下一个位置int k;// 一会儿开辟的队列大小为 k+1} MyCircularQueue; bool myCircularQueueIsEmpty(MyCircularQueue* obj); bool myCircularQueueIsFull(MyCircularQueue* obj);// 前面先实现的函数要用到这两个接口,所以事先声明一下// 循环队列的初始化 MyCircularQueue*myCircularQueueCreate(int k){ MyCircularQueue* cq =(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); cq->a =(int*)malloc(sizeof(int)*(k+1)); cq->front =0;// 初始化数据 cq->tail =0; cq->k = k;return cq;}// 入队 bool myCircularQueueEnQueue(MyCircularQueue* obj,int value){if(myCircularQueueIsFull(obj))return false;// 满了就不能再入了 obj->a[obj->tail]= value;// 将数据入进来++obj->tail;// 更新tail obj->tail %=(obj->k+1);// tail 自增了之后可能超出循环队列的大小范围所以要取模// 模的是循环队列的大小 k+1return true;}// 出队 bool myCircularQueueDeQueue(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return false;// 为空就不能再删 obj->front =(obj->front+1)%(obj->k+1);// 和前面是一样的原理,注意同样是加一再取模return true;}// 获取队头元素intmyCircularQueueFront(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return-1;return obj->a[obj->front];}// 获取队尾元素intmyCircularQueueRear(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return-1;if(obj->tail ==0)return obj->a[obj->k];// 跨越了一个循环的情况elsereturn obj->a[obj->tail-1];}// 判空 bool myCircularQueueIsEmpty(MyCircularQueue* obj){return obj->front == obj->tail;}// 判满 bool myCircularQueueIsFull(MyCircularQueue* obj){return(obj->tail+1)%(obj->k+1)== obj->front;// tail的后一个是front说明满了,但是有可能tail+1跨过了一个循环。所以要取模}// 释放voidmyCircularQueueFree(MyCircularQueue* obj){free(obj->a);// 注意这里要先释放结构体内的数组!!!不然会可能内存泄漏free(obj);}

Read more

【图文】Windows + WSL + Ubuntu 安装 OpenClaw 全套流程(飞书机器人 + 百炼模型)

目录 * 一、安装 WSL * 二、安装基础组件 * 三、安装 Node.js(通过 nvm) * 1 安装 nvm * 2 安装 Node * 四、安装 OpenClaw * 五、OpenClaw 初始化配置 * 六、Hooks 配置(重要) * 七、打开 Web UI * 八、安装飞书插件 * 九、第三方飞书插件(备用方案) * 十、飞书权限配置(注意先做好飞书机器人设置,再配置channel) * 十一、配置飞书channel * 十二、配置飞书回调事件 * 十三、重启 OpenClaw * 十四、配置百炼模型

雷达信号处理中的CFAR技术详解

好的,我来为您总结归纳雷达信号处理中的恒虚警(CFAR)技术,并提供一个基于MATLAB的实际用例。 🧐 雷达信号处理之恒虚警(CFAR) 恒虚警率(Constant False Alarm Rate, CFAR)是一种自适应阈值目标检测技术,在雷达信号处理中用于从噪声和杂波背景中检测出目标回波。其核心思想是:无论背景噪声或杂波的功率如何变化,都保持虚警概率( )为一个预先设定的常数。 🎯 1. 基本原理与流程 CFAR算法通过实时估计待检测单元(Cell Under Test, CUT)周围的背景噪声或杂波功率,并根据期望的虚警率 自适应地确定检测阈值 。 主要步骤: 1. 滑动窗口(Detection Window):在待检测数据(通常是距离-多普勒图或距离向数据)上设定一个固定大小的滑动窗口。 2. 单元划分:窗口内的单元被划分为三个部分: * 待检测单元(CUT):位于窗口中心,是我们要判断是否包含目标的单元。 如果 ,则判断不存在目标(No Target)。 如果 ,则判断存在目标(

构建 基于无人机 RGB+红外(RGBT)双模态小目标行人检测系统 无人机视角下RGB+红外对齐行人小目标检测数据集 航拍无人机多模态行人检测数据集 红外可见光行人检测数据集

构建 基于无人机 RGB+红外(RGBT)双模态小目标行人检测系统 无人机视角下RGB+红外对齐行人小目标检测数据集 航拍无人机多模态行人检测数据集 红外可见光行人检测数据集

无人机视角下RGB+红外对齐行人小目标检测数据集 模态与视角:无人机搭载 RGBT 双光相机,从 50–80 m 高度、45°–60° 俯视角采集,同步 RGB + 热红外图像对。 规模:6,125 对图像(4,900 train / 1,225 test),分辨率 640×512,共 70,880 个行人实例。 任务:专门面向 tiny person detection 的无人机 RGBT 检测 benchmark。 1 1 以下是 无人机视角下 RGB+红外对齐行人小目标检测数据集 的详细信息整理成表格:

【数字图像处理与FPGA实现】00 绪,建立“算法思维“与“硬件思维“的桥梁

【数字图像处理与FPGA实现】00 绪,建立“算法思维“与“硬件思维“的桥梁

0、初衷 我的历程: 算法->rtl -> 算法&rtl 构建起这座桥,双向互译!直到 “写算法时心中有电路,写FPGA时心中有算法。” 阶段1:我曾是算法的"原教旨主义者"。 最早期,我和许多算法工程师一样,活在 MATLAB/Python/C语言 的抽象象牙塔里。 对我来说,图像就是 imread() 返回的那个完美矩阵, 处理就是调用 conv2() 或 cv2.GaussianBlur()等函数。 数据是静止的、无限的、免费的——内存不够就加条 DIMM, 算得慢就等几秒,边界处理? MATLAB 会帮我 padarray, Python 会帮我