你真的了解环形队列吗?(学习数据结构必须掌握的模型)
目录
0.前言
1. 什么是环形队列
2. 如何使用数组结构 / 链表结构 对环形队列封装
3. 代码手撕环形队列各个接口
3.1 代表封装一个环形队列
3.2 环形队列的初始化
3.3 环形队列的插入
3.4环形队列的删除
3.5环形队列的判空
3.6环形队列的判满
3.7环形队列的队头
3.8环形队列的队尾
3.9环形队列的销毁
0.前言
4栈和队列OJ题集合/CircularQueue.h · onlookerzy123456qwq/data_structure_practice_primer - 码云 - 开源中国 (gitee.com)
https://gitee.com/onlookerzy123456qwq/data_structure_practice_primer/blob/master/4%E6%A0%88%E5%92%8C%E9%98%9F%E5%88%97OJ%E9%A2%98%E9%9B%86%E5%90%88/CircularQueue.h本文所有代码资源已经上传至gitee,如上可自取。
622. 设计循环队列 - 力扣(LeetCode)
https://leetcode.cn/problems/design-circular-queue/这是本题的OJ链接,是骡子是马,可以拉出去练练。
1. 什么是环形队列
环形队列,也称循环队列,它是一种特殊的队列,则其必首先符合队列的性质,即先进先出,后进后出(First In First Out)。
环形队列特殊在哪里呢?
1.这个队列是定长的,在初始化的时候,这个队列的长度就已经定了,即再也不能改变它所能容纳元素的最大数量了。
2.这个队列从抽象图看来,形状上不是平常我们看到是直线型的,而是一个环形的。
3.这个队列的队头和队尾(首和尾),在插入删除的过程当中,是一直在不断变化的。相比普通队列,它的首尾并不是在完全固定的位置。
环形队列的逻辑是:一个head记录当前环形队列的队头位置,一个tail记录当前环形队列的队尾位置(当然我们这里tail实际代表意义是队尾元素的下一个位置),如果删除的话就前移head代表删除,如果要插入的话,就后移tail,代表增加一个环形队列的元素。这是环形队列的插入删除逻辑。
那环形队列毕竟是定长的队列,当超过定长,即把这个环形队列插满时,那就会插入失败。所以我们需要设定一个head和tail的状态,以之作为判断环形队列是否为满的标准。同时我们也要设定一个head和tail的状态,以之作为判断环形队列是否为空的标准。
我们这样设定:初始状态的环形队列,即环形队列是空的话,此时head和tail是重合的。
然后你插入一个元素,队列是从队尾插入的,所以我们就把当前tail所指向的位置插入新元素,然后++tail,指向队尾的下一个位置(因为如果不++tail的话,head和tail还是重合的,这是时候,我们是认为此环形队列是空)。
如果再一直一直插入新元素,直到插入为满的时候,(tail能最远到达的位置决定了最多能插入的元素,而且铭记tail指向的是队尾元素的下一个位置,head和tail重合代表环形队列为空),根据上述规则的限定,我们最终可以允许tail最远到head的前一个位置。
这样虽然会浪费掉一个小元素的空间,但是这就一小点并不重要,实在不行,你想最多插入k个有效元素,你再多开一个元素的空间(k+1)不就中了嘛~
当然啦,删除元素,队列就是删除队头的元素,然后head指向的就是队头元素,我们++head即可完成删除。
2. 如何使用数组结构 / 链表结构 对环形队列封装
使用链表结构进行对一个环形队列的实现,我们很简单,就是用head和tail两个指针,然后记录一个当前长度int num,然后就依次进行对于该队列的插入删除,这个和我们这篇博客所写的j基本一样:3.用C语言实现队列
然后我们再需要做的就是,当总数据num达到了定长,即达最大可容纳数目之后,那我们就禁止插入,这个很简单的。
本博客,我们使用数组结构来仿生实现该环形队列,你可能会产生疑问:链表姑且可以通过next成员指针找到下一个元素做到首尾相接,那一个数组的首尾又不相连,怎么会实现出一个环形队列呢?其实,我们是借助 % array_len 的方式,实现的一手首尾互通,可以循环的走。
举一个简单的例子:
我们在插入的时候,是直接在tail位置进行插入(因为tail始终是指向最后一个队尾元素的下一个元素),但是上图当中,我们刚刚插入7这个元素之后,就需要我们++tail,但是这样就完了吗?这样会产生越界,而且你是环形队列,你index==8的下一个位置应该是循环回头[0]!!!我们的解决方法是%arr_len的方式。(8 + 1)之后再 % 数组长度9,结果是0,就回到了数组头的位置了!!!
3. 代码手撕环形队列各个接口
3.1 代表封装一个环形队列
我们选择了数组结构实现环形队列,那么我们就要在堆区开辟一个数组,所以我们存储封装一个数组指针成员int* _a。
然后任何一个环形队列都是定长的,所以我们不妨定义一个int _k,代表当前队列最多能存储的有效元素的数量。(这个_k也是)
然后环形队列控制首尾也是必要的,所以我们定义一个head和tail分别管理队头和队尾,即分别负责删除和插入(tail指代的是队尾元素的下一个位置,空时与head重合)。
//我们使用数组来模拟实现循环队列
typedef struct {int* _a; //数组实体int _k; //最大容纳有效数据个数int _head; //队头[删除]int _tail; //队尾[插入]
} MyCircularQueue;
3.2 环形队列的初始化
我们创建一个环形队列,或者任何一个类对象,就要对之完成初始化,这里我们把创建环形队列的方法封装成一个接口myCircularQueueCreate,返回的是一个在堆区创建环形队列的指针,然后在这个接口当中我们对之完成初始化。
MyCircularQueue* myCircularQueueCreate(int k) {//在堆区开辟一个环形队列变量MyCircularQueueMyCircularQueue* p_circularQueue = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));p_circularQueue->_k = k;p_circularQueue->_head = 0;p_circularQueue->_tail = 0; //默认一开始首尾指针指向[0]的位置//构造可以存储k个有效数据的环形队列空间,需要我们开辟k+1的空间int* ptmp = (int*)malloc(sizeof(int)*(k+1));if(ptmp==NULL){exit(1);}p_circularQueue->_a = ptmp;//返回创造的环形队列实体return p_circularQueue;
}
3.3 环形队列的插入
这里要两个需要特别注意的点:一个判断当前环形队列是否为满,环形队列是定长的,如果为满就是插入失败。第二个点是,tail的更新需要考虑从尾至首。
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//向循环队列插入一个元素。如果成功插入则返回真。//循环队列存满了就不让存了,所以存在false插入失败的情况//1.判断是否为满(tail->next==head)//tail的next不能简单++,我们需要考虑到从数组尾[k]到数组头[0]的情况,所以(tail++);tail%=(k+1);即可int next_tail = (obj->_tail+1)%(obj->_k+1);if(next_tail==obj->_head){return false;}//2.进行插入obj->_a[obj->_tail] = value;//更新tailobj->_tail = next_tail;return true;
}
3.4环形队列的删除
如果为空,不能删除;删除就是直接++head,更新头的位置即可完成(伪删除法),但是此时还时要考虑head从尾至首这样的一个特殊情况。
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//从循环队列中删除一个元素。如果成功删除则返回真。//存在是空的环形队列,所以存在删除失败false的情况//1.判断是否为空:head与tail重合if(myCircularQueueIsEmpty(obj)) //obj->_head==obj->_tail{return false;}//2.删除就是把head++,指向下一个元素即可 //可是head也存在从数组尾更新到数组头的情况obj->_head++;obj->_head%=(obj->_k+1);return true;
}
3.5环形队列的判空
我们设定head和tail重合的时候为空。
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//两个指针重合代表空return obj->_head==obj->_tail;
}
3.6环形队列的判满
满的时候我们设定的状态是tail的next值就是head,那就是满状态。(当然这里要记住:我们存在从数组尾n-1到头0的转变,所以说不能直接无脑对tail+1哦)
bool myCircularQueueIsFull(MyCircularQueue* obj) {//tail->next==head代表满return (((obj->_tail)+1)%(obj->_k+1))==obj->_head;
}
3.7环形队列的队头
int myCircularQueueFront(MyCircularQueue* obj) {//从队首获取元素。如果队列为空,返回 -1 。//存在从空队列中取数据的情况,这种情况是非法情况if(myCircularQueueIsEmpty(obj)){return -1;}//队头的数据,就是head指向的数据return obj->_a[obj->_head];
}
3.8环形队列的队尾
int myCircularQueueRear(MyCircularQueue* obj) {//获取队尾元素。如果队列为空,返回 -1 。//存在从空队列中取数据的情况,这种情况是非法情况if(myCircularQueueIsEmpty(obj)){return -1;}//tail指向的是下一个要插入的数据的位置//所以上一个队尾的数据应该是tail-1的位置//但是在这种情况下,tail也有从队首回到队尾的情况出现//所以我们需要淡出讨论这种情况if(obj->_tail == 0){return obj->_a[obj->_k];}return obj->_a[obj->_tail-1];
}
3.9环形队列的销毁
环形队列的成员变量都是定义在堆区的,然后指向的数组空间也是存储在堆区的,我们使用完环形队列要对之销毁。
void myCircularQueueFree(MyCircularQueue* obj) {//释放所有的堆区空间free(obj->_a);free(obj);
}
相关文章:

你真的了解环形队列吗?(学习数据结构必须掌握的模型)
目录 0.前言 1. 什么是环形队列 2. 如何使用数组结构 / 链表结构 对环形队列封装 3. 代码手撕环形队列各个接口 3.1 代表封装一个环形队列 3.2 环形队列的初始化 3.3 环形队列的插入 3.4环形队列的删除 3.5环形队列的判空 3.6环形队列的判满 3.7环形队列的队头 3.8环…...

《痞子衡嵌入式半月刊》 第 72 期
痞子衡嵌入式半月刊: 第 72 期 这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻,农历年分二十四节气,希望在每个交节之日准时发布一期。 本期刊是开源项目(GitHub: JayHeng/pzh-mcu-bi-weekly),欢迎提交 issue,…...

对redis之键值型数据库的理解
键值数据库,首先就要考虑里面可以存什么样的数据,对数据可以做什么样的操作,也就是数据模型和操作接口。它们看似简单,实际上却是我们理解 Redis 经常被用于缓存、秒杀、分布式锁等场景的重要基础。理解了数据模型,你就…...

Linux内核中的软中断、tasklet和工作队列
软中断、tasklet和工作队列并不是Linux内核中一直存在的机制,而是由更早版本的内核中的“下半部”(bottom half)演变而来。下半部的机制实际上包括五种,但2.6版本的内核中,下半部和任务队列的函数都消失了,…...

【Java】Spring Boot 2 集成 nacos
官方文档:https://nacos.io/zh-cn/docs/quick-start-spring-boot.html pom 本次Springboot版本 2.2.6.RELEASE,nacos-config 版本 0.2.7,nacos-discovery版本 0.2.7 parent <parent><groupId>org.springframework.boot</gr…...

JavaSE学习笔记day14
二、Set Set集合是Collection集合的子接口,该集合中不能有重复元素!! Set集合提供的方法签名,与父接口Collection的方法完全一致!! 即没有关于下标操作的方法 Set接口,它有两个常用的子实现类HashSet,TreeSet 三、HashSet HashSet实现了Set接口,底层是hash表(实际上底层是HashM…...

LLVM高级架构介绍
LLVM 为什么要开一个LLVM的新坑呢? 我从智能穿戴转行到芯片软件行业,从事编译器开发,不过是AI编译器。不过基本的传统编译器还是绕不过去啊,所以开始学习LLVM,后面开始学习TVM,MLIR。 LLVM GitHub地址 L…...
全网最经典函数题型【详解】——C语言
文章目录1. 写一个函数可以判断一个数是不是素数。2. 写一个函数判断一年是不是闰年。3. 写一个函数,实现一个整形有序数组的二分查找。4. 写一个函数,每调用一次这个函数,就会将 num 的值增加1。5. 写一个函数,打印乘法口诀表。6…...

emqx桥接配置+常见问题解决+jmeter压测emqx
一,桥接资源配置及规则配置 Emqx桥接配置流程 1,配置资源并测试连接通过 规则引擎——>资源——>新建——>选择MQTT Bridge——>填写参数测试连接 参数描述详见3.1资源配置 2,配置规则 2.1根据实际业务选择合适sql 规则引擎…...

improve-1
类型及检测方式 1. JS内置类型 JavaScript 的数据类型有下图所示 其中,前 7 种类型为基础类型,最后 1 种(Object)为引用类型,也是你需要重点关注的,因为它在日常工作中是使用得最频繁,也是需要…...

华为OD机试用Python实现 -【云短信平台优惠活动】(2023-Q1 新题)
华为OD机试题 华为OD机试300题大纲云短信平台优惠活动题目描述输入描述输出描述示例一输入输出说明示例二输入输出说明Python 代码实现代码编写思路华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看…...

Facebook广告投放运营中的关键成功因素是什么?
在当今数字化的时代,广告投放已经成为了各种企业获取市场份额和增加品牌曝光的重要手段之一。Facebook作为全球最大的社交媒体平台之一,其广告投放运营的成功,将直接影响企业的品牌推广和市场营销效果。本文将探讨Facebook广告投放运营中的关…...

2023年1月综合预订类APP用户洞察——旅游市场复苏明显,三年需求春节集中释放
2023年1月,随着国家对新型冠状病毒感染实施“乙类乙管”,不再对入境人员和货物等采取检疫传染病管理措施,并且取消入境后全员核酸检测和集中隔离,横亘在旅游者与旅游目的地之间的隔阂从此彻底消失。2023年1月恰逢春节假期…...

基于stm32计算器设计
这里写目录标题 完整de代码可q我获取1 系统功能设计2 系统硬件系统分析设计2.1 STM32单片机核心电路设计2.2 LCD1602液晶显示模块电路设计2.3 4X4矩阵键盘模块设计3 STM32单片机系统软件设计3.1 编程语言选择3.2 Keil程序开发环境3.3 FlyMcu程序烧录软件介绍3.4 CH340串口程序烧…...
基于SpringCloud的可靠消息最终一致性02:项目骨架代码(上)
在上一节中咱们已经把分布式事务问题交代了一遍,包括两大定理、五大解决方案和一个成熟的开源框架,而咱们最终的目标是用Spring Cloud实现一个实际创业项目的可靠消息最终一致性的分布式事务方案。 先交代一下项目背景。 前几年,社会上慢慢兴起一种称为C2C同城快递的业务,也…...

RockerMQ集群部署
目录一、Broker集群模式1、单Master:2、多Master多Slave模式异步复制3、多Master多Slave模式同步双写二、集群搭建实践1、集群架构2、克隆生成rocketmqos13、修改rocketmqos1配置文件4、克隆生成rocketmqOS25、修改rocketmqOS2配置文件6、启动服务器7、测试一、Brok…...

unicloud的aggregate聚合查询时间戳转日期
我特么不知道看了这个帖子几百遍才看明白到-----》unicloud数据库中,聚合操作如何操作时间戳? - DCloud问答 自己淋过雨老想着为别人撑伞,可怜我这35岁的老人家,给我去点关注!!!!&a…...

Vue2.0开发之——使用ref引用组件实例(41)
一 概述 在本组件内部修改count的值在父组件内修改子组件的count值 二 在本组件内部修改count的值 2.1 Left.vue 布局代码 <template><div class"left-container"><h3 >Left 组件---{{count}}</h3><button click"count 1"&…...
极狐GitLab仓库瘦身
参考文章: [分享] 极狐GitLab仓库瘦身 - 官方技术分享 - 极狐GitLab 论坛 一、瘦身概述 Git仓库随着时间推移会变得越来越大,比如很多比较大的文件加入Git仓库时,可能引起以下问题: 下载仓库越来越慢,因为每个人都…...

2288hv5超融合服务器 数码管报888
【问题现象】 2288hv5超融合服务器,前面板数码管报888,电源灯黄灯闪烁,开不了机,ibmc网络是通的,但是web网页打不开 【问题原因】 iBMC的版本过低,iBMC在智能诊断数据库保护机制存在异常,导…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...