622.设计循环队列(LeetCode)

news2024/11/25 6:53:56

思路

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

这里有两种解决方案

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.coloradmin.cn/o/1213990.html

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

相关文章

asp.net数字档案管理系统VS开发sqlserver数据库web结构c#编程web网页设计

一、源码特点 asp.net 数字档案管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语 言开发。 asp.net数字档案系统1 应用技…

通过右键用WebStorm、Idea打开某个文件夹或者在某一文件夹下右键打开当前文件夹用上述两个应用

通过右键用WebStorm、Idea打开某个文件夹或者在某一文件夹下右键打开当前文件夹用上述两个应用 通过右键点击某个文件夹用Idea打开 首先打开注册表 win R 输入 regedit 然后找到HKEY_CLASSES_ROOT\Directory\shell 然后右键shell 新建一个项名字就叫 Idea 第一步&#xf…

【FPGA】zynq 单端口RAM 双端口RAM 读写冲突 写写冲突

RAMRAM读写分类RAM原理及实现RAM三种读写模式不变模式写优先读优先 单端口 RAM伪双端口 RAM真双端口 RAM读写冲突和写写冲突读写冲突写写冲突总结: RAM RAM 的英文全称是 Random Access Memory,即随机存取存储器,简称随机存储器,…

ProtoBuf的学习和使用(C++)

ProtoBuf的学习和使用---C ⼀、初识ProtoBuf序列化和反序列化的概念ProtoBuf是什么?ProtoBuf工作特点 二、主要学习思路三、快速上手四、proto3语法详解1.字段规则2.消息类型的定义与使⽤实际操练 3.enum枚举类型enum注意事项enum实操 4.Any类型Any类型实操 5.oneof类型oneof类…

滴滴 Redis 异地多活的演进历程

为了更好的做好容灾保障,使业务能够应对机房级别的故障,滴滴的存储服务都在多机房进行部署。本文简要分析了 Redis 实现异地多活的几种思路,以及滴滴 Redis 异地多活架构演进过程中遇到的主要问题和解决方法,抛砖引玉,…

Unity Meta Quest 一体机开发(六):HandGrabInteractor 和 HandGrabInteractable 知识点

文章目录 📕教程说明📕HandGrabInteractor⭐HandGrabAPI⭐HandWristPoint⭐GripPoint⭐PinchPoint⭐PinchArea⭐HandGrabVisual⭐HandGrabGlow 📕HandGrabInteractable⭐Support Grab Type⭐Pinch Grab Rules 和 Palm Grab Rules⭐Unselect M…

【SpringBoot3+Vue3】三【实战篇】-后端(优化)

目录 一、登录优化-redis 1、SpringBoot集成redis 1.1 pom 1.2 yml 1.3 测试程序(非必须) 1.4 启动redis,执行测试程序 2、令牌主动失效(代码优化) 2.1 UserController设置token到redis 2.2 登录拦截器Log…

下载huggingface预训练模型到本地并调用

写在前面 在大模型横行的时代,无法在服务器上连接外网的研究僧真的是太苦逼了,每次想尝试类似于CLIP,BLIP之类的大模型都会得到“requests.exceptions.ConnectionError: (MaxRetryError("HTTPSConnectionPool(host‘huggingface.co’, …

Win11系统安装或执行程序时提示:文件系统错误(-1073740771)解决方案

有用户反映,exe文件无法执行或者无法安装,报错如图所示: 解决方法: 方法一: 1.打开控制面板,可以采用”搜索“→”控制面板“的方式 2.控制面板选择“用户账户”,再选择“更改用户账户控制设…

TiDB单机集群模拟生产环境

1、先部署环境,安装5.4.3版本,详细的安装步骤见官方文档:单机集群模拟生产环境安装教程 配置文件topo.yaml global:user: "tidb"ssh_port: 22deploy_dir: "/tidb-deploy"data_dir: "/tidb-data"monitored:no…

【数据结构】线段树(点修区查)

数据结构-线段树(点修区查) 前置知识 分治递归二叉树 思路 我们需要维护一个支持单点修改,区间查询的数据结构,并且要求在线,一般使用线段树解决。 线段树是一个二叉树形的数据结构。 线段树的思想很简单&#xff0c…

Python---数据序列中的公共方法

公共方法就是 支持大部分 数据 序列。 常见公共方法---简单 运算符描述支持的容器类型合并字符串、列表、元组*复制字符串、列表、元组in元素是否存在字符串、列表、元组、字典not in元素是否不存在字符串、列表、元组、字典 案例: 合并 代码: # …

阿里云99元VS腾讯云88元,双11云服务器价格战,谁胜谁负?

在2023年的双十一优惠活动中,阿里云推出了一系列令人惊喜的优惠活动,其中包括99元一年的超值云服务器。本文将带您了解这些优惠活动的具体内容,以及与竞争对手腾讯云的价格对比,助您轻松选择最适合的云服务器。 99元一年服务器优…

使用SSH和SCP传输文件———详细入门教学实践

确保你已经在本地机器上安装了SSH客户端和SCP工具。 获取远程虚拟机的IP地址或主机名以及登录凭据(用户名和密码或私钥)。 打开终端(命令提示符)并输入以下命令来传输文件: scp /本地路径/文件 用户名远程虚拟机IP地…

ubuntu设置脚本开机自启动

rc-local.service flexmitd1:~$ cd /lib/systemd/system/ flexmitd1:/lib/systemd/system$ ls |grep rc-local.service rc-local.service rc-local.service.d flexmitd1:/lib/systemd/system$ pwd /lib/systemd/system flexmitd1:/lib/systemd/system$确保有rc-local.service文…

深入理解JMM(Java内存模型)

一、什么是JMM? Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的一组规则或者规范。通过这些规则、规范定义了程序中各个变量的访问方式。jvm运行的程序的实体是线程,而每个线程运行时,都会创建一…

C# - 委托、事件、Action、Func

前言:所有的名词,都是基于委托产生的 委托 (delegate) 解释: 其实就是一种指定格式的函数模版(容器) 这个模版(容器)可以用来存放各种格式和它相同的函数(的引用) 比如指定类型参数 指定参数个数 指定返回值等等 定义…

社区论坛小程序系统源码+自定义设置+活动奖励 自带流量主 带完整的搭建教程

大家好啊,又到了罗峰来给大家分享好用的源码的时间了。今天罗峰要给大家分享的是一款社区论坛小程序系统。社区论坛已经成为人们交流、学习、分享的重要平台。然而,传统的社区论坛往往功能单一、缺乏个性化设置,无法满足用户多样化的需求。而…

无人零售:创新优势与广阔前景

无人零售:创新优势与广阔前景 无人零售在创新方面具有优势。相比发展较为成熟的欧洲和日本的自动贩卖机市场,中国的无人零售市场人均占有量较少,这表明该市场具有广阔的前景和巨大的市场潜力。 此外,无人零售涉及到许多相关行业&…

GD32_ADC采样+DMA多通道扫描传输

GD32_ADC采样DMA多通道扫描传输 文章目录 GD32_ADC采样DMA多通道扫描传输前言一、资源介绍二、原理1.ADC连续扫描模式2.DMA传输3.ADC内部通道 三、配置1.ADC配置2.DMA配置3.注意事项 四、计算1.分压转换2.数据转换 前言 <1>、硬件平台&#xff1a;可运行软件程序的GD32单…