622.设计循环队列(LeetCode)

思路

先确定什么情况为空,什么情况为满

这里有两种解决方案

1.留一个空间空置,当rear+1 == front时 ,则队列为满 (这里我们选用方案一)

2.增加一个size变量记录数据个数,size == 0则为空,size == k则为满

第一部分,确定为空的情况,我们规定:当front == rear时,队列为空(此时rear表示的是尾部元素的下一位,和栈中的top有异曲同工之妙)。

第二部分,确定为满的情况,当rear+1 == front时 ,则队列为满

实现一(用链表实现)

我们先来分析一下链表实现的场景,先给一个单向循环链表

push 1 2 3 4 5,此时达到了满的条件:rear->next == front 

pop 2次 ,front只用往后两个节点即可,并不用修改数据(因为后面继续push会覆盖)

 此时不满,又可以继续push 6 7,rear接着向后移动,并且插入新数据

 这样看起来,是不是链表实现还挺简单的?但是,这里有一个接口就很难受了——获取队尾数据

有没有解决方法呢?肯定有,只是比较麻烦。 有三种解决方案,第一种双向链表,第二种增加一个rearPrev指针,每次rear往后移时,rearPrev要记录前一个位置,第三种遍历获取队尾数据

那有人可能会说,我可以让rear指向队尾元素,那开头rear就必须指向NULL,又多出了对空指针的判断。所以牵一发而动全身,这里用链表实现可以,但比较麻烦。 

实现二 (用数组实现 )

那么链表实现比较麻烦,数组实现就简单吗?确实!这里用数组实现队列,代码会简洁不少,所以这里详细讲解用数组实现,有兴趣的小伙伴也可以去实现链表。

同样,先给一个空数组,满足front == rear的条件 

 push 1 2 3 4 5,此时rear+1 == front,达到满的条件。可是,rear+1 ==front是我们假想它是循环的,现实中应该怎么书写判满的条件呢?

假设循环队列存储k个有效数据,此时k == 5,开辟6个空间。  标出下标,那么此时我们可以利用取模,得出(rear+1)%(k+1)== front 的条件,其中k+1是空间个数,此时rear==5,+1为6,取模6,就变为0,就与front相等了(是不是很神奇?)

 

让我们再来看看其他情况 ,我们先pop 3次,让队列可以插入

 push 6 7 8 9,最后一个失败,此时又为满,再来分析一下:rear==2,+1为3,取模6,还是3,正好是front(是不是又验证了一遍我们的判断条件?)

分析了这么久,我们终于要开始写代码了。 

先创建MyCircularQueue结构体,并对其初始化 (这里就省略申请失败的条件,因为oj题基本不会申请失败),注意这里记得数组a开辟k+1个空间

和分析一样,先写出判空和判满的函数 ,有了前面的分析,这里是不是就很好理解了?

空:front == rear

满:(rear+1)%(k+1)==  front

 向循环队列插入数据,先判断队列是否为满,如果不满,在队尾rear插入数据,rear++(不过注意,rear有可能在边界,++要循环回来,所以最后%=(k+1));如果为满,则返回false,表示插入失败。

 从循环队列删除数据,同样也先判断队列是否为空,如果不空,则front++,再%=(k+1);如果为空,则表示删除失败,返回false

 获取队头元素,这个也超级简单。先判断是否为空,不为空,则直接返回下标为front的元素;如果为空,则返回-1

 获取队尾数据关键点来了。我们就是因为链表实现这个功能复杂,才选择了数组,让我们来看看数组是怎样实现这个功能的呢?一般情况,rear如果不在边界,我们就返回下标为rear-1的元素,如果rear刚好在最左边,那就返回下标为k的元素。这里可以用一个条件判断来写代码。

但是,有一种更妙的方法,先判断是否为空,不为空,则返回下标为(rear+k)%(k+1)的元素。这是什么意思呢?其实完整的写是(rear-1+k+1)%(k+1),相当于rear为0是,rear-1为-1,但是此时加上k+1,再取模k+1,就变成了k。(是不是很妙?) 

 最后,就是简单的释放空间,先释放数组空间,再释放队列空间。

完整代码附上:

typedef struct {int front;int rear;int k;int* a;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->front = obj->rear = 0;obj->k = k;obj->a = (int*)malloc((k+1)*sizeof(int));return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front == obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->rear+1) % (obj->k+1) == obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if (!myCircularQueueIsFull(obj)){obj->a[obj->rear] = value;obj->rear++;obj->rear %= (obj->k+1);return true;}return false;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if (!myCircularQueueIsEmpty(obj)){obj->front++;obj->front %= (obj->k+1);return true;}return false;
}int myCircularQueueFront(MyCircularQueue* obj) {if (!myCircularQueueIsEmpty(obj)){return obj->a[obj->front];}return -1;
}int myCircularQueueRear(MyCircularQueue* obj) {if (!myCircularQueueIsEmpty(obj)){return obj->a[(obj->rear+obj->k)%(obj->k+1)];}return -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.rhkb.cn/news/193602.html

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

相关文章

RabbitMQ之死信队列

文章目录 一、死信的概念二、死信的来源三、实战1、消息 TTL 过期2、队列达到最大长度3、消息被拒 总结 一、死信的概念 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说&#x…

AI创作系统ChatGPT网站源码+详细搭建部署教程+支持DALL-E3文生图/支持最新GPT-4-Turbo-With-Vision-128K多模态模型

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

010.cat、find

1、用cat进行拼接 cat命令能够显示或拼接文件内容,不过它的能力远不止如此。比如说,cat能够将标准输入数据与文件数据组合在一起。通常的做法是将stdin重定向到一个文件,然后再合并两个文件。而cat命令一次就能搞定这些操作。 用cat读取文件…

Java排序算法之希尔排序

希尔排序(Shell Sort)又称“缩小增量排序”,是直接插入排序算法的一种更高效的改进版本。它的基本思想是:首先将整个数组按照一定的间隔分成若干个子序列,然后对每个子序列分别进行插入排序,减小间隔&#…

2023双十一爆冷收场,订单后暗藏这些电商痛点问题需要注意

打开某软件的瞬间,手不小心抖一下就进入了淘宝,而且无法第一时间准确找到关闭按钮。相信不少人都在这个双十一通过开屏广告为淘宝“贡献”至“超8亿”的访问量,更有网友辣评:“现在打开别的软件跳转淘宝的速度都比直接打开淘宝要快…

大语言模型量化方法对比:GPTQ、GGUF、AWQ

在过去的一年里,大型语言模型(llm)有了飞速的发展,在本文中,我们将探讨几种(量化)的方式,除此以外,还会介绍分片及不同的保存和压缩策略。 说明:每次加载LLM示例后,建议清除缓存,以…

【LIUNX】配置缓存DNS服务

配置缓存DNS服务 A.安装bind bind-utils1.尝试修改named.conf配置文件2.测试nslookup B.修改named.conf配置文件1.配置文件2.再次测试 缓存DNS服务器:只提供域名解析结果的缓存功能,目的在于提高数据查询速度和效率,但是没有自己控制的区域地…

虹科方案 | 从概念到生产的自动驾驶软件在环(SiL)测试解决方案

来源:雅名特自动驾驶 虹科方案 | 从概念到生产的自动驾驶软件在环(SiL)测试解决方案 自动驾驶软件在环(SiL)测试解决方案 自动驾驶软件在环(SiL)测试解决方案能够研究和验证高历程实验和恶劣驾…

计算属性与watch的区别,fetch与axios在vue中的异步请求,单文本组件使用,使用vite创建vue项目,组件的使用方法

7.计算属性 7-1计算属性-有缓存 模板中的表达式虽然很方便,但是只能做简单的逻辑操作,如果在模版中写太多的js逻辑,会使得模板过于臃肿,不利于维护,因此我们推荐使用计算属性来解决复杂的逻辑 <!DOCTYPE html> <html lang"en"> <head><meta …

初试 jmeter做压力测试

一.前言 压力测试是每一个Web应用程序上线之前都需要做的一个测试&#xff0c;他可以帮助我们发现系统中的瓶颈问题&#xff0c;减少发布到生产环境后出问题的几率&#xff1b;预估系统的承载能力&#xff0c;使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步…

BMS系统项目

1、通过电压监测是否冲满&#xff0c;通过电压可以监测是否放完电 电池得参数 单体过压&#xff08;充满电&#xff09; 过压恢复&#xff08;百分之90多&#xff09; 欠压保护&#xff08;百分之几得电&#xff0c;快关机了&#xff09; 欠压恢复&#xff08;就是欠压之上…

【博客系统】 一

该博客系统基于servlet和mysql数据库 , 并且通过xshell终端工具部署至云服务器. 实现的功能包括: 1.博客列表页 2.博客详情页 3.登陆页面 4.强制登陆检查 5.获取用户信息 6.退出登陆 7.发布博客 一.系统展示 登陆页面 博客列表页 博客详情页 博客编辑页 下面就开始编写代码了.…

【Java 进阶篇】JQuery 案例:下拉列表选中条目左右移动,打破选择的边界

在前端的舞台上&#xff0c;下拉列表是常见的用户交互元素&#xff0c;但有时候我们想要更多的交互体验。通过巧妙运用 JQuery&#xff0c;我们可以实现下拉列表中选中条目的左右移动功能&#xff0c;为用户提供更加灵活的选择方式。本篇博客将深入研究 JQuery 中实现这一功能的…

基于安卓android微信小程序的师生答疑交流平app

项目介绍 本课题研究的是基于HBuilder X系统平台的师生答疑交流APP&#xff0c;开发这款师生答疑交流APP主要是为了帮助用户可以不用约束时间与地点进行所需信息。本文详细讲述了师生答疑交流APP的界面设计及使用&#xff0c;主要包括界面的实现、控件的使用、界面的布局和异常…

C语言从入门到精通之【基本运算符】

赋值运算符 在C语言中&#xff0c;并不意味着“相等”&#xff0c;而是一个赋值运算符。下面的赋值表达式语句&#xff1a; bmw 2002; 把值2002赋给变量bmw。也就是说&#xff0c;号左侧是一个变量名&#xff0c;右侧是赋给该变量的值。符号被称为赋值运算符。另外&#xff0…

【数电】IEEE754浮点数

IEEE754浮点数 1.组成及分类2.计算(1)符号位(2)阶码(3)尾码(4)实际计算公式 1.组成及分类 &#xff08;1&#xff09;组成 IEEE754浮点数由三部分组成&#xff1a;符号位、阶码和尾码。 &#xff08;2&#xff09;分类 根据数据位宽分为三类&#xff1a;短浮点数、长浮点数和…

54. 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1a;matrix [[1,2,3,…

【Android】配置Gradle打包apk的环境

目录 生成jks签名文件 配置build.gradle&#xff08;app&#xff09; 打包 生成jks签名文件 Java 密钥库&#xff08;.jks 或 .keystore&#xff09;是用作证书和私钥存储库的二进制文件。用于为用户设备上安装的 APK 签名的密钥。 详细解释请看官方文档&#xff1a; 为应用…

Zookeeper Java SDK 开发入门

文章目录 一、概述二、导入依赖包三、与 Zookeeper 建立连接四、判断 ZooKeeper 节点是否存在四、创建 ZooKeeper 节点数据五、获取 ZooKeeper 节点数据六、修改 ZooKeeper 节点数据七、异步获取 ZooKeeper 节点数据八、完整示例 如果您还没有安装Zookeeper请看ZooKeeper 安装说…

如何调整图片尺寸:简单实用的教程分享

报名事业编考试的时候&#xff0c;会发现上传照片时会提示图片大小尺寸应该为多少&#xff0c;如果不符合规定就无法提交报名&#xff0c;那么怎么才能修改图片大小呢&#xff1f;最简单的方法就是利用调整照片大小工具来对图片尺寸修改&#xff0c;本文分享一个在线图片处理工…