数据结构刷题训练:设计循环队列(力扣OJ)

目录

文章目录

前言

1. 题目:设计循环队列

2. 思路

3. 分析

 3.1 定义循环队列

 3.2 创建队列

 3.3 判空和判满

 3.4 入队

 3.5 出队

 3.6 取队头队尾数据

 3.7 销毁队列

 4. 题解

总结


前言

        当谈到队列数据结构时,很多人可能会想到普通的队列,即先进先出(FIFO)的数据结构。然而,有时候我们需要一种更高效的队列实现方式,这就是循环队列。


1. 题目:设计循环队列

 题目描述:

 题目链接:

设计循环队列icon-default.png?t=N6B9https://leetcode.cn/problems/design-circular-queue/

2. 思路

        先来理解一下题意,首先队列的长度为定长k,其次就是队列可以循环利用空间。这里我们要思考一下是使用链表实现,还是使用数组实现。在设计这个环形队列的时候,我们肯定是要设计头和尾的入下图:

         当前状态视为队列满,这时如果出队元素就会空出空间此时我们可以继续入队数据如下图:

         后边满了以后再插入数据它可以绕回来,这就是循环队列。从front开始道rear结束就是队列的数据。或许有人会有疑惑:为什么不把尾指向最后一个元素,而是指向最后一个元素的后一个位置?

        这样是为了便于判断队列是否为空,我们举个例子,队列为空时front和rear是都指向开头的,如果插入一个数据,rear就要向后移动,不移动就无法判断队列是否为空。

接下来我们回到开始的问题,使用数组还是链表实现?

         我们依据上一个问题,知道rear指向的是队尾的后一个元素,那依据单链表的特性取队尾不好取。如果要好取尾就要用双向循环链表会好搞一些,当然还有其他的解决办法例如:多加一个变量size记录队列数据个数,rear指向队尾,这样也可以解决,但这样写代码会很容易让人误导,所以这里不推荐这样的方法。链表实现也是可以的,但相对数组的代码量就比较多了。使用数组实现也会简单方便的多。

 数组:

         当rear+1==front时就是为满,由于它是一个循环队列,rear在末尾后再+1就会回到头,这里可以写成这样:front==(rear+1)%(k+1)(取值范围0~k),它要始终保持front与rear之间留有一个空。这里我们就使用数组来实现。

3. 分析

        依据上述的思路,我们使用数组来实现循环队列,通过上述的思路我们可以发现这个规律,出队就front向后走,入队就rear向后走。

 3.1 定义循环队列

typedef struct {int* a;int front;int rear;int k;
} MyCircularQueue;

        a用于存放数据,和顺序表类似,使用malloc开辟空间。front为队头,rear为队尾。

 3.2 创建队列

MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//多开一个空间obj->a=(int*)malloc(sizeof(int)*(k+1));obj->front=obj->rear=0;obj->k=k;return obj;
}

         这里和之前一样,我们仅仅是定义了队列的类型,并没有创建结构体变量,为了便于后续传参,这里我们使用malloc创建一个结构体变量。有了obj就可以通过它来找到结构体中的各个成员。注意我们还需要对数组a进行开辟空间。

 3.3 判空和判满

         这里我们先来实现判满和判空操作,上述思路中我们多开辟一个空间,用于判断满和空的情况,如果rear等于front就为空,如果rear+1等于front就为满。接下来我们来实现一下:

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return (obj->front==obj->rear);
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->front==(obj->rear+1));
}

         但这样写对吗?这样写是不对的,前边思路中提到:front==(rear+1)%(k+1)为了达到返回开头的目的,所以这里需要改写(也是为了防止rear+1越界)。

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

        这里可能就有人疑惑了,为什么rear需要模k+1返回,front就不需要呢?front也会走到尾啊。

这个当然是需要考虑的,这个操作是在出队操作时考虑的,在判满时可以不考虑,满的情况分为两种:

第一种:

 第二种:

 3.4 入队

 

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj))return false;obj->a[obj->rear]=value;obj->rear++;obj->rear%=(obj->k+1);return true;
}

         入队操作非常简单,在入队之前先判断队是否满,如果满直接返回false(错误)。不为满就将rear位置入队数据,然后rear向后移动,这里为了便于rear返回,这里rear需要%=(k+1)。

过程如下:

 

 3.5 出队

 

bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return false;obj->front++;obj->front %=(obj->k+1);return true;
}

         出队前要先判断队列是否为空,不为空就front++即可不需要任何修改(front开始到rear直接的为有效数据),为了便于front返回,这里可以使用取模,或者使用if语句判断,都可以。

 

 再次入队数据就会将原数据自动覆盖。

 3.6 取队头队尾数据

         取队头数据非常简单

int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[obj->front];
}

         如果为空就直接返回-1,如果不为空就返回数组front下标的数据。重点在于队尾数据。

         一般情况队尾数据只需要rear-1就可以了,但是这里需要考虑rear为0的情况。如果rear为0,rear-1就越界非法访问了,我们需要的是rear返回到数组最后的位置。这里我们可以这样操作,既然我们是取模让rear达到返回到0,那我们在对rear取模之前先对rear+(k+1),这样rear取模后仍然可以取到下标为0的位置,-1就回到了最后的位置(减一后:(rear+k)%(k+1)结果为k)

 (rear+(k+1)-1)%k+1化简一下就是:(rear+k)%(k+1),代码实现:

int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[(obj->rear+obj->k)%(obj->k+1)];
}

 3.7 销毁队列

        销毁队列也非常简单,先销毁啊数组,再销毁obj。

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

 4. 题解

 整体代码:

typedef struct {int* a;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->a=(int*)malloc(sizeof(int)*(k+1));obj->front=obj->rear=0;obj->k=k;return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return (obj->front==obj->rear);
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->front==(obj->rear+1)%(obj->k+1));
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj))return false;obj->a[obj->rear]=value;obj->rear++;obj->rear%=(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;elsereturn obj->a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[(obj->rear+obj->k)%(obj->k+1)];
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}

 力扣上边也是可以通过的。

 

         通过整体代码实现我们可以发现:数组实现循环队列需要特别注意边界问题,一不注意就会出现错误。


 

总结

        希望本博客能够帮助您更好地理解和应用循环队列,为您的学习和工作带来帮助。让我们继续探索数据结构的奥秘,不断提升自己的编程能力吧!

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

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

相关文章

Python-OpenCV中的图像处理-霍夫变换

Python-OpenCV中的图像处理-霍夫变换 霍夫变换霍夫直线变换霍夫圆环变换 霍夫变换 霍夫(Hough)变换在检测各种形状的技术中非常流行,如果要检测的形状可以用数学表达式描述,就可以是使用霍夫变换检测它。即使要检测的形状存在一点破坏或者扭曲也是可以使…

ThinkPHP8命名规范-ThinkPHP8知识详解

本文主要讲解thinkphp8的命名规范,主要包括:遵循PHP自身的PSR-2命名规范和PSR-4自动加载规范、目录和文件命名规范、函数和类、属性命名规范、常量和配置命名规范、数据表和字段命名规范、不能使用PHP保留字。 在使用thinkphp8开发项目之前,…

Docker安装ElasticSearch/ES 7.4.0

目录 前言安装ElasticSearch/ES安装步骤1:准备1. 安装docker2. 搜索可以使用的镜像。3. 也可从docker hub上搜索镜像。4. 选择合适的redis镜像。 安装步骤2:拉取ElasticSearch镜像1 拉取镜像2 查看已拉取的镜像 安装步骤3:创建容器创建容器方…

【软件测试】Linux环境Ant调用Jmeter脚本并且生成测试报告(详细)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 准备工作 需要在…

Linux驱动-基于Buildroot构建系统镜像后实现基于QT项目开发之环境配置

Linux驱动-基于Buildroot构建系统镜像后实现基于QT项目开发之环境配置 需求BuildRootUboot的仓库地址和commit idKernel 的仓库地址和commit id BuildRoot已编译库在Windows上的Create上创建项目编译QT项目 需求 基于Build root编译整个镜像后,如何开发自己的基于Q…

windows环境下打印机无法打印的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【资讯速递】AI与人类思维的融合;OpenAI在中国申请注册“GPT-5”商标;移动大模型主要面向to B 智能算力是未来方向

2023年8月11日 星期五 癸卯年六月廿五 第000001号 欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文收录于IT资讯速递专栏,本专栏主要用于发布各种IT资讯,为大家可以省时省力的就能阅读和了解到行业的一些新资讯 资…

【BASH】回顾与知识点梳理(十五)

【BASH】回顾与知识点梳理 十五 十五. 指令与文件的搜寻15.1 脚本文件名的搜寻which (寻找『执行档』) 15.2 文件档名的搜寻whereis (由一些特定的目录中寻找文件文件名)locate / updatedbfind与时间有关的选项与使用者或组名有关的参数与文件权限及名称有关的参数额外可进行的…

【图像分类】 理论篇(1) 图像分类的测评指标

对于分类模型的性能评估通常采用混淆矩阵的方式和计算准确率、正确率、召回率和 F1 分数。本文详细介绍图像分类的测评指标 在二分类问题中,样本有正负两个类别,模型对样本的预测结果存在四种组合:真阳性,即预测为正&#x…

Axure RP9小白安装教程

Axure RP 9是一款流行的快速原型设计软件,用于创建交互式原型。它提供了丰富的工具和功能,方便用户设计和演示WEB界面、APP界面以及软件界面等产品的交互效果。Axure RP 9可以帮助产品经理、设计师和开发团队更好地协作,快速验证和改进产品的…

ROS实现自定义信息以及使用

常见的消息包 消息包定义一般如下👇 (1)创建包和依赖项 (2)在新建的qq_msgs的包新建msgs的文件夹,在该文件夹里面新建Carry.msg类型的文件。 其实,Carry.msg就是你自己定义的消息类型&am…

JVM之内存模型

1. Java内存模型 很多人将Java 内存结构与java 内存模型傻傻分不清,java 内存模型是 Java Memory Model(JMM)的意思。 简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据…

2023 互联网大厂薪资大比拼

最近整理了33家互联网大厂的薪资情况。可以看出来,大部分互联网大厂薪资还是很不错的,腾讯、阿里、美团、百度等大厂平均月薪超过30k,其他互联网大厂平均月薪也都在25k以上。01020304050607080910111213141516171819202122232425262728293031…

无涯教程-Perl - glob函数

描述 此函数返回与EXPR匹配的文件的列表,这些文件将由标准Bourne shell进行扩展。如果EXPR未指定路径,请使用当前目录。如果省略EXPR,则使用$_的值。 从Perl 5.6开始,扩展是在内部完成的,而不是使用外部脚本。扩展遵循csh(以及任何派生形式,包括tcsh和bash)的扩展方式,其翻译…

MFC 多语言对话框

可以直接看一下bilibili的这个本人录制的视频:MFC资源多语言_哔哩哔哩_bilibili 这里所说的多语言也是国际化 新建一个MFC项目,我这边是中文简体,如果想加入其他语言,方法如下: 修改完这些之后,需要在代码…

1990-2021年上市公司绿色专利和绿色使用新型申请获得分类号数据

1990-2021年上市公司绿色专利申请获得分类号数据 1、时间:1990-2021年 2、来源:国家知识产权局 3、指标: 绿色专利申请数量(分A类 B类C类D类E类F类G类H类)、绿色专利获得数量(分A类 B类C类D类E类F类G类…

198、仿真-基于51单片机函数波形发生器调幅度频率波形Proteus仿真(程序+Proteus仿真+原理图+流程图+元器件清单+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、原理图 五、程序源码 资料包括: 需要完整的资料可以点击下面的名片加下我,找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选…

ubuntu20.04磁盘满了 /dev/mapper/ubuntu--vg-ubuntu--lv 占用 100%

问题 执行 mysql 大文件导入任务,最后快完成了,查看结果发现错了!悲催!都执行了 两天了 The table ‘XXXXXX’ is full ? 磁盘满了? 刚好之前另一个 centos 服务器上也出现过磁盘满了,因此&a…

Spring Cloud 面试突击2

Spring Cloud 面试突击2 高并发:是一种系统运行过程中遇到的短时间大量的请求操作 响应时间: 吞吐量: QPS:数据库为维度 TPS 并发用户数 并发的维度:很多的 并发是不是达到的当前系统的瓶颈 缓存 &#xff08…

matlab解常微分方程常用数值解法2:龙格库塔方法

总结和记录一下matlab求解常微分方程常用的数值解法,本文将介绍龙格库塔方法(Runge-Kutta Method)。 龙格库塔迭代的基本思想是: x k 1 x k a k 1 b k 2 x_{k1}x_{k}a k_{1}b k_{2} xk1​xk​ak1​bk2​ k 1 h f ( x k , t …