Leetcode:622. 设计循环队列 题解【具详细】

目录

一、题目:

二、思路详解:

1.循环队列的存储定义

2.循环队列的创建

3.循环队列的判空与判断情况

(1) 循环队列的判空:

 (2) 循环队列的判满

4.循环队列元素的插入

5.循环队列元素的删除

6.获取队头元素

7.获取队尾元素 

8.循环队列释放

三、完整代码展示:


一、题目:

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

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

你的实现应该支持如下操作:

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。

难度:中等

题目链接:622. 设计循环队列

示例:

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1);  // 返回 true
circularQueue.enQueue(2);  // 返回 true
circularQueue.enQueue(3);  // 返回 true
circularQueue.enQueue(4);  // 返回 false,队列已满
circularQueue.Rear();  // 返回 3
circularQueue.isFull();  // 返回 true
circularQueue.deQueue();  // 返回 true
circularQueue.enQueue(4);  // 返回 true
circularQueue.Rear();  // 返回 4

题目解析:就是根据题中给的接口进行函数的实现。要求我们实现一个循环队列。

用心阅读下方会有很大的收获。 

二、思路详解:

1.循环队列的存储定义

首先我们需要定义出一个循环队列的存储定义,这里采用的是使用动态数组来进行模拟循环队列,根据题中给出的接口返回类型,我们可以知道循环队列的数据类型为int 。

其次,还需定义两个记录数组的下标,一个记录队列的队头,另一个记录队列的队尾(也就是指向要入队的下一个元素的位置)。另外还要提供一个表示要存储数据的具体个数。

如图:

代码:

//采用动态数组的形式来模拟循环队列
typedef struct {int* a;     //指向数组int front;  //队头int tail;   //队尾int k;      //数据个数
} MyCircularQueue;

2.循环队列的创建

循环队列的创建,先使用malloc进行创建一个 循环队列空间

接着根据给的数据个数k让指针a指向一个动态数组,在分别对front,tail,k进行初始化,注意tail = 0表示要存放的下一个数据元素的位置,对动态数组a开辟空间的时候要多开辟一个空间,避免假溢出的现象。最后一定要返回之前创建的循环队列。

代码:

//创建长度为k的循环队列
MyCircularQueue* myCircularQueueCreate(int k) {//使用动态内存函数来申请内存//这里多申请一个空间的目的是防止假溢出//使用malloc创建一个循环队列MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//为循环队列里面的指针a ,让a指向一个长度为k+1的数组obj->a= (int*)malloc(sizeof(int)*(k+1));obj->front = 0; //队头从数组的下标0开始obj->tail = 0; //队尾指向下一个元素obj->k = k; //队列的长度为kreturn obj;
}

物理存储情况,如图:

但是我们一般会到其循环的逻辑结构,逻辑存储,如图:

 3.循环队列的判空与判断情况

循环队列的插入和删除是不可避免的,当这之前就需要先完成判和判满的接口。注意:一定要把判空和判满的函数实现放在队列插入和删除函数实现的前面。

(1) 循环队列的判空:

根据函数的返回类型是bool,空我们就返回true ,否则返回false。

  • isEmpty(): 检查循环队列是否为空。

因为这里采取的是通过动态数组来模拟循环队列,所以队列空的条件就是当front == tail 的时候,此时的循环队列就是空的。

如图:

代码:

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//队空,就是队头与队尾相同时return obj->front == obj->tail;
}
 (2) 循环队列的判满

 同样根据函数的返回类型是bool,空我们就返回true ,否则返回false。

  • isFull(): 检查循环队列是否已满。

什么时候会满呢?当(tail+1)%(k+1) == front,就是队尾下标加1模开辟空间的个数 

可能很多会对为什么要多开辟一个空间,原因就在这:对于队列的判满的情况,

当没有创建的额外空间,队列只有数据10 和 11 的情况下,

像上图就是假溢出现象,这个队列并没有满。

总的来说:

循环队列为了区分队列的空和满,需要额外增加一个空的元素来占据队列的一个位置,这样队列满的状态就可以通过头尾指针相邻且不重合来判断,而不会出现头尾指针重合但队列实际上并不满的情况。同时循环队列需要对头尾指针进行模运算,如果没有额外的空间,那么当队列最后一个元素占据了数组最后一个位置时,下一个元素就会从数组的第一个位置开始,这样就无法正确进行模运算,而增加一个空的元素可以解决这个问题。

 代码:

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

 4.循环队列元素的插入

  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。

插入前判断是否满,满就返回false,接着就是数据的插入,插入后,对tail下标进行取模(因为是反复利用原来的空间,还有就是避免溢出),插入成功就返回true。

 代码:

//插入元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//插入元素前先进行判断是否满if(myCircularQueueIsFull(obj)){return false;}//插入元素使用尾插obj->a[obj->tail] = value;obj->tail++;//避免tail的下标越界obj->tail%=(obj->k+1);return true;
}

5.循环队列元素的删除

 删除前,要进行判断是否为空。队头减一,进行删除,删除后取模。

  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。

 代码:

//出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//删除元素队列不能为空if(myCircularQueueIsEmpty(obj)){return false;}//出队,头删obj->front++;obj->front%=(obj->k+1);return true;
}

 6.获取队头元素

获取前进行判断,是否为空。

Front: 从队首获取元素。如果队列为空,返回 -1  

  代码:

//获取队首元素
int myCircularQueueFront(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}return obj->a[obj->front];
}

7.获取队尾元素 

获取前进行判断,是否为空。

Rear: 获取队尾元素。如果队列为空,返回 -1  

  代码:

//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}//注意当tail = 0的情况return obj->a[(obj->tail - 1+ obj->k+1)%(obj->k+1)];
}

解释一下 上述最后一行代码:

重点:

首先tail是指向要存放下一个元素的位置,找队尾元素时,tail要进行-1。

 因为数组下标最小是从0开始的,当tail ==0且队列不为空的情况下,上方代码obj->tail-1,就会造成0-1 == -1的情况。上方采用(obj->tail - 1+ obj->k+1)%(obj->k+1)就可以完美的避免,当然

其实可以写成

int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;// return obj->a[(obj->tail-1 + obj->k+1)%(obj->k+1)];if(obj->tail == 0){return obj->a[obj->k];}else{return obj->a[obj->tail-1];}
}

8.循环队列释放

 因为用malloc开辟的动态内存空间,为了避免内存泄漏,我们还要释放内存。注意释放的顺序。

 代码:

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

三、完整代码展示:

 代码: 


//采用动态数组的形式来模拟循环队列
typedef struct {int* a;     //指向数组int front;  //队头int tail;   //队尾int k;      //数据个数
} MyCircularQueue;//创建长度为k的循环队列
MyCircularQueue* myCircularQueueCreate(int k) {//使用动态内存函数来申请内存//这里多申请一个空间的目的是防止假溢出//使用malloc创建一个循环队列MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//为循环队列里面的指针a ,让a指向一个长度为k+1的数组obj->a= (int*)malloc(sizeof(int)*(k+1));obj->front = 0; //队头从数组的下标0开始obj->tail = 0; //队尾指向下一个元素obj->k = k; //队列的长度为kreturn obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//队空,就是队头与队尾相同时return obj->front == obj->tail;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->tail+1)%(obj->k+1) == obj->front;
}//插入元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//插入元素前先进行判断是否满if(myCircularQueueIsFull(obj)){return false;}//插入元素使用尾插obj->a[obj->tail] = value;obj->tail++;//避免tail的下标越界obj->tail%=(obj->k+1);return true;
}//出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//删除元素队列不能为空if(myCircularQueueIsEmpty(obj)){return false;}//出队,头删obj->front++;obj->front%=(obj->k+1);return true;
}//获取队首元素
int myCircularQueueFront(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}return obj->a[obj->front];
}//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}//注意当tail = 0的情况return obj->a[(obj->tail - 1+ obj->k+1)%(obj->k+1)];
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}/*** Your MyCircularQueue struct will be instantiated and called as such:* MyCircularQueue* obj = myCircularQueueCreate(k);* bool param_1 = myCircularQueueEnQueue(obj, value);* bool param_2 = myCircularQueueDeQueue(obj);* int param_3 = myCircularQueueFront(obj);* int param_4 = myCircularQueueRear(obj);* bool param_5 = myCircularQueueIsEmpty(obj);* bool param_6 = myCircularQueueIsFull(obj);* myCircularQueueFree(obj);
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/159601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

打不开clickonce问题解决过程

1.用户电脑user文件夹下有xx和xx.1两个账户,原先安装在xx账户下,后修了电脑原数据保留在xx.1,新创建XX,之后clickonce就打不开了表现为没有反应,,删除注册表和appdata都只能正常安装,但是不能打开,没有任何报错,发现在我的电脑下打开有这样的提示,,在用户电脑上没有 尝试通过修…

大家为什么开始配置长效IP代理?长效IP代理有什么优势?

随着网络技术的发展,越来越多的人开始关注网络安全和隐私保护。其中,长效IP代理作为一种安全、高效的解决方案,受到了越来越多人的关注。本文将探讨大家为什么开始配置长效IP代理,以及长效IP代理的优势。 一、长效IP代理的优势1.保…

目前市面上进销存软件有哪些?那个牌子靠谱?

目前市面上进销存软件有哪些?哪个牌子靠谱? 说起进销存软件,如果你是没用过,正在寻找一款合适的,你是不是遇到了以下问题: 公司多部门协作还在用Excel,没有信息化支撑?跨部门存在信…

C语言——深入理解指针——函数指针

一、函数指针变量 1.1 函数指针变量的创建 什么是函数指针变量呢&#xff1f; 函数指针变量应该是用来存放函数地址的&#xff0c;未来通过地址能够调⽤函数的。 那么函数是否有地址呢&#xff1f; 我们做个测试&#xff1a; #include <stdio.h> void test() {print…

软考中级哪个科目最简单?

那必须是系统集成项目管理工程师&#xff01; 系统集成项目管理工程师考试内容少&#xff0c;题型简&#xff0c;报考门槛低&#xff0c;零基础就能报考&#xff0c;学习内容比较简单&#xff0c;接近工作和生活。 系统集成项目管理工程师证书是中国计算机技术职业资格&#…

2024年湖北省水利厅的安管人员水安ABC证报考指南

2024年湖北省水利厅的安管人员水安ABC证报考指南 关于水安ABC报考&#xff0c;很多企业乃至个人都不是很清楚流程&#xff0c;叙后尘来给大家科普一下报考详细细节。2023年年度仅剩一次的报考时间定于2023年11月23日至11月28日。在这个时间段才可以网上填写报考资料&#xff0…

js读取json文件

1. 原生的两种方法 1.1 XMLHttpRequest const xhr new XMLHttpRequest(); xhr.overrideMimeType("application/json"); xhr.open(GET, data.json, true); xhr.onreadystatechange function () {if (xhr.readyState 4 && xhr.status 200) {const data …

使用EasyPlayer播放H.265视频流

使用EasyPlayer播放H.265视频流 EasyPlayer流媒体视频播放器 EasyPlayer流媒体视频播放器 EasyPlayer流媒体视频播放器可支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff0c;能支持RTSP、RTMP、HLS、FLV、WebRTC等格式的视频流播放&#xff0c;并且已实现网页…

Cannot read properties of undefined (reading ‘resetFields‘)“ 报错解决

遇到这种报错 先去相关页面搜索关键字 定位到具体的报错代码 Cannot read properties of undefined (reading ‘resetFields’)" 关键字&#xff1a;resetFields 此方法作用&#xff1a;对整个表单进行重置 将所有字段值重置为初始值并移除校验结果 报错场景&#xff1a;…

坚鹏:湖北银行数字化转型背景下银行运营管理创新培训圆满结束

湖北银行正式成立于2011年2月27日&#xff0c;总部设在武汉。现有员工5000余人。营业网点从成立之初的93家增长至241家&#xff0c;实现全省17个市州、59个县域营业网点全覆盖。截至2022年末&#xff0c;全行资产总额4026亿元&#xff0c;存款总额2956亿元&#xff0c;贷款总额…

人工标签不准确的一种解决方案:PCA降维可视化筛选正样本

背景 在实际的业务场景里&#xff0c;用会话文本构建模型&#xff08;机器学习/深度学习&#xff09;来做意图分类之类的任务时&#xff0c;经常会出现人工打标不够准确的问题&#xff0c;标签都不准确的话模型当然无法学习到有效信息了。这个问题真的非常头疼…除了与业务沟通…

d3dcompiler_47.dll缺失怎么修复,d3dcompiler_47.dll的作用有哪些

d3dcompiler_47.dll丢失是一种常见的电脑问题。如果你遇到了这个问题&#xff0c;不要惊慌&#xff0c;下面的方法可以帮助你解决。本文将详细介绍解决d3dcompiler_47.dll丢失问题的步骤&#xff0c;让你手把手地学会。 一.解决d3dcompiler_47.dll丢失问题的步骤 解决方法一&a…

CSS伪类选择器详细讲解

前言 伪类选择器在CSS中起到的作用可以说是至关重要的&#xff0c;如果CSS没有伪类选择器&#xff0c;有很多效果都要借助js来完成&#xff0c;这样不仅代码量增加&#xff0c;维护起来你难度也大。这样程序员的工作量大&#xff0c;也违背了CSS诞生的作用&#xff0c;就是提高…

重磅!TikTok Shop将以新方式重启印尼业务

据报道&#xff0c;TikTok将通过与印尼电商平台合作的方式重启电商业务。 据悉&#xff0c;印尼合作社和中小企业部就TikTok Shop将在印尼重新开业的消息发表了讲话。合作社和中小企业部Temmy Satya Permana证实TikTok Shop将在印尼重新开业的消息。他表示&#xff0c;TikTok …

使用 Python脚本在3DMAX中加载图像和读取图像中的像素值

如何使用Python在3dmax中加载和显示图像文件&#xff1f;我们先看下面的代码&#xff1a; *测试的3dmax文件和图像文件位于同一目录中。 from MaxPlus import BitmapManagerimage_file_path rje_gray_02_4k.exrbmp_storage MaxPlus.Factory.CreateStorage(17)bmp_info bmp…

探索数字孪生的潜力:五个最有前景的行业

数字孪生技术正在引领一场新的工业革命&#xff0c;其潜力正在被全球范围内的行业所认识和利用。在未来&#xff0c;数字孪生技术将在许多行业中发挥重要作用&#xff0c;本文带大家共同解析未来数字孪生技术五个最有发展前景的行业。 1.制造业 数字孪生技术可以帮助制造商模…

Leetcode——169 多数元素

我的答案 class Solution {public int majorityElement(int[] nums) {int len nums.length;Arrays.sort(nums);int count 1;int res 0;if(len 1){return nums[0];}for(int i0; i<len-1; i){if(nums[i]nums[i1]){count;}else{count 1;}if(count>len/2){res nums[i]…

【问题定位】通过看Mybatis源码解决系统问题

开发需求好好的&#xff0c;运维同事突然发现了一个问题&#xff0c;某个任务的详情页面加载不出来。看日志&#xff0c;系统在进行查询操作的时候抛出空指针异常。感觉是Mybatis内部异常&#xff0c;所以就跟踪源码看下Mybatis运行到哪一步报错的。 DefaultSqlSession#select…

2023年亚太杯数学建模思路 - 案例:粒子群算法

文章目录 1 什么是粒子群算法&#xff1f;2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Pa…

PostgreSQL导出表结构带注释

我们在平时开发过程中&#xff0c;经常会在字段的注释中&#xff0c;加上中文&#xff0c;解释字段的相关含义&#xff0c;也可以避免时间太久忘记这个字段代表什么&#xff0c;毕竟英文水平不好。我们可能要经常整理数据库表结构&#xff0c;提供他人去收集数据&#xff0c;但…