设计循环队列——oj题622

news2024/10/6 18:23:06

在这里插入图片描述在这里插入图片描述

.

个人主页:晓风飞
专栏:LeetCode刷题|数据结构|Linux
路漫漫其修远兮,吾将上下而求索


文章目录

  • 题目要求:
    • 应该支持如下操作:
    • 示例:
    • 提示:
  • 结构体定义
  • 队列的创建
  • 基本操作
    • 判断队列是否为空:
    • 判断队列是否已满:
    • 入队操作:
    • 出队操作:
    • 获取队首和队尾元素:
    • 内存释放
  • 难点解释
    • 难点1
    • 难点2
    • 难点3


要做题目的点击这里–>队列oj题——622.设计循环队列

题目要求:

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

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

应该支持如下操作:

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

示例:

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

提示:

所有的值都在 0 至 1000 的范围内;
操作数将在 1 至 1000 的范围内;
请不要使用内置的队列库。
在这里插入图片描述

结构体定义

首先,我们定义一个名为 MyCircularQueue 的结构体来表示循环队列:

typedef struct {
    int *a;     // 队列中的元素数组
    int k;      // 队列的最大容量
    int front;  // 指向队列头部元素的指针
    int back;   // 指向队列尾部的下一个位置的指针
} MyCircularQueue;

在这个结构体中,a 是一个整型数组,用来存储队列中的元素。k 表示队列的最大容量,front 和 back 分别表示队列头部和尾部的指针。

队列的创建

队列的创建涉及到内存的分配和初始化:

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int *)malloc(sizeof(int)*(k+1));
    obj->front = obj->back = 0;
    obj->k = k;
    return obj;
}

这里,我们为队列结构体和队列数组分配内存。注意,我们为数组分配 k+1 的空间,因为在循环队列中,我们总是保留一个位置不使用,以区分队列为空和队列为满的状态。

基本操作

判断队列是否为空:

// 检查队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->back; // 如果 front 和 back 相等,则队列为空
}

frontback 相等时,队列为空。

判断队列是否已满:

// 检查队列是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->back + 1) % (obj->k + 1) == obj->front; 
    // 如果 back 的下一个位置是 front,则队列已满
}

如果 back 的下一个位置是 front,则队列已满。

入队操作:

// 向队列中添加元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj)) // 如果队列已满,则无法添加元素
        return false;

    obj->a[obj->back] = value; // 在 back 的位置插入元素
    obj->back = (obj->back + 1) % (obj->k + 1); // 更新 back 的位置

在入队时,我们首先检查队列是否已满。如果不满,将元素放在 back 指向的位置,并更新 back 指针。

出队操作:

// 从队列中删除元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) // 如果队列为空,则无法删除元素
        return false;

    obj->front = (obj->front + 1) % (obj->k + 1); // 更新 front 的位置
    return true;
}

出队时,我们检查队列是否为空。如果不为空,则移动 front 指针。

获取队首和队尾元素:

// 获取队列头部的元素
int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) // 如果队列为空,返回 -1
        return -1;
    return obj->a[obj->front]; // 返回队列头部的元素
}

// 获取队列尾部的元素
int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) // 如果队列为空,返回 -1
        return -1;
    return obj->a[(obj->back - 1 + obj->k + 1) % (obj->k + 1)]; // 返回队列尾部的元素
}

这两个函数用于获取队首和队尾的元素。注意在获取队尾元素时,我们使用了模运算来正确处理环形结构。

内存释放

最后,当队列不再需要时,我们应该释放其占用的内存:

// 释放队列占用的内存
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a); // 释放数组内存
    free(obj);    // 释放队列结构体内存
}

难点解释

难点1

在这里插入图片描述
这里我优化了代码,没有优化前是这样的:

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj)) // 如果队列已满,则无法添加元素
        return false;

    obj->a[obj->back] = value; // 在 back 的位置插入元素
    obj->back++; // 更新 back 的位置
    obj->back %=(obj->k+1);//确保值在循环队列的有效范围内
    return true;
}

难点2

在这里插入图片描述

1.循环队列的容量:在这个循环队列的实现中,队列的实际容量是 k + 1,但为了区分空队列和满队列的状态,我们总是保留一个元素的空间不使用。所以,队列中最多可以存储 k 个元素。

2.队列尾部指针 (obj->back):这个指针指向队列中下一个元素将要存放的位置。当一个新元素被加入队列时,它被放置在 obj->back 指向的位置,然后 obj->back 会向前移动一个位置。

3.队列头部指针 (obj->front):这个指针指向队列中当前的第一个元素。当一个元素被移出队列时,obj->front 会向前移动一个位置。

4.判断队列是否已满:
(obj->back + 1) % (obj->k + 1) 计算出 obj->back 向前移动一个位置后的值,并使用模运算确保这个值在循环队列的有效范围内(即从 0 到 k)。


难点3

在这里插入图片描述

下面是这个表达式的详细解释:

1.obj->back: 指向队列中下一个插入元素的位置。

2.obj->back - 1: 因为 obj->back 指向的是下一个空位,所以队尾元素实际上是在 obj->back - 1 的位置。

3.由于队列是循环的,当 obj->back 为 0 时,obj->back - 1 会变成一个负数。为了正确地处理这种情况,我们加上 obj->k + 1,这保证了我们总是在一个正数的范围内操作。

4.(obj->back - 1 + obj->k + 1) % (obj->k + 1): 这个模运算确保了即使加上了 obj->k + 1,结果仍然是在队列大小的合法范围内。因此,这个表达式能够正确地处理循环队列的尾部元素访问,无论 obj->back 是在队列的开始位置还是任何其他位置

可以来我的github参观参观,看完整代码
路径点击这里–>oj622-设计循环队列

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

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

相关文章

基于springboot+vue的家政服务系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

汇报学习1

汇报的重点 项目的意义:可复制的经验、未来的领头基层要多具体的案例且真正有意义提拔的人的标准 汇报的维度 多做定期和主动的回报。 适当的工作汇报,也是对对方尊重的体现。(每一周或每两三天的回报里,要体现对领导的尊重&#…

buildroot 编译错误【001】

在GitHub 查找错误,也挺好用 解决办法 fakeroot 错误 还是用docker构建编译环境安全,镜像解压脚本,写错了位置,生产环境被覆盖,唉 … …

Apache Commons Email在邮件发送中的应用

第1章:简介 大家好,我是小黑,今天咱们聊聊Apache Commons Email这个库,它在发送邮件方面可谓是小而美的利器。Apache Commons Email基于JavaMail API,但它提供了更简洁、更易用的接口,让咱们在处理电子邮件…

“神秘巨鲸”将数十亿USDT转入交易所!花旗前高管,绕过美证监会发行比特币证券!比特币将迎来拉涨行情?

在监管机构是否会放行比特币ETF的猜测达到白热化之际,一群前花旗集团管理人士成立了一家名为Receipts Depositary Corporation(RDC)的初创公司,计划向全球机构投资者发行首批比特币存托凭证,还称这种证券无需美国监管机…

大数据平台数据治理与建设方案:PPT全文90页,附下载

关键词:数据治理,大数据,数据治理平台,数据治理顶层设计,大数据治理,数据治理建设 一、数据治理建设需求分析 1、业务需求和目标:首先,明确业务需求和目标是非常重要的。数据治理项…

win7系统报错msvcp140.dll丢失的多种解决方法分享

在Windows 7操作系统中,msvcp140.dll是一个非常重要的动态链接库文件,它负责许多应用程序的正常运行。然而,由于各种原因,我们可能会遇到丢失msvcp140.dll的问题。当msvcp140.dll文件丢失或损坏时,可能会导致程序无法启…

手机流量卡推广分销网站php源码,多功能的号卡推广分销管理系统

源码简介 拥有多个接口,包括运营商接口,并支持无限三级代理。 最简单易用的PHP系统,它自带自动安装向导,可以让你轻松安装和部署。 该系统集成了多个第三方接口资源,能够满足你的不同需求。采用全系统双色主题&…

案例094:基于微信小程序的图书馆自习室座位预约管理系统

文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…

51单片机之按键和数码管

51单片机之按键和数码管 ✍前言:♐独立按键😀独立按键的原理😀软件实现按键控制LED灯的亮灭 ♐数码管😊数码管显示数字或者字母的原理🐉共阳极数码管🐉共阴极极数码管🐉4位1体数码管 &#x1f6…

解决:Microsoft Visual C++ 14.0 is required.

Microsoft Visual C 14.0 is required. Get it with “Microsoft Visual C Build Tools 当我们安装绝大部分python包的时候可以通过pip install 或者 conda install解决,但是任然有些包是安装不了的,比如我的就是在安装pyqt5的时候报Building wheel for…

Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机掉线自动重连(C) Baumer工业相机Baumer工业相机的图像转换为OpenCV的Mat图像的技术背景在NEOAPI SDK里实现相机图像转换为Mat图像格式联合OpenCV实现相机图像转换为Mat图像格式测试演示图 工业相机…

整合【事务】

目录 1、读未提交(脏读) 2、读已提交(不可重复读) 3、可重复读(幻读) 4、Navicat中模拟开启、提交、回滚事务 1、读未提交(脏读) 允许一个事务读取其他事务未提交的修改 2、读已…

Nginx 的 gzip 压缩

目录 1. 为什么要开启gzip 压缩 2.对网站配置文件进行修改 1. 为什么要开启gzip 压缩 nginx使用gzip压缩主要是为了降低网站的带宽消耗和提升访问速度。通过对页面进行压缩,可以减少传输的数据量,从而减少网络传输的时间和带宽消耗。 当浏览器接收到压…

c语言-函数指针

目录 前言一、函数指针1.1 函数指针定义1.2 函数指针调用函数1.3 函数指针代码分析 总结 前言 本篇文章介绍c语言中的函数指针以及函数指针的应用。 一、函数指针 函数指针:指向函数的指针。 函数在编译时分配地址。 &函数名 和 函数名代表的意义相同&#xf…

Linux的ping命令、wget命令、curl命令

一、ping命令 通过ping命令,可以检查指定的网络服务器是否是可联通状态 形式:ping [-c num] ip或主机名 -c:检查的次数,不使用-c,将无限次数持续检查 ip或主机名:被检查的服务器的ip地址或主机名地址 …

透明OLED屏的稳定性:从技术角度及应用案例解析

在显示技术日新月异的今天,透明OLED屏以其独特的透明特性和出色的显示效果,吸引了众多关注。然而,对于这种新型技术的稳定性,人们难免会有所疑虑。作为一名专注于OLED技术研发的工程师,尼伽小编将从专业角度出发&#…

数据结构(五)——初识线性表

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉 在csdn获奖荣誉: 🏆csdn城市之星2名 ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ …

【Java集合篇】HashMap 在 get 和 put 时经过哪些步骤

HashMap在get和put时经过哪些步骤? ✔️ 典型解析✔️get方法✔️put方法✔️ 拓展知识仓✔️ HashMap如何定位key✔️ HashMap定位tablelndex的骚操作作✔️HashMap的key为null时,没有hashCode是如何存储的?✔️ HashMap的value可以为null吗? 有什么优缺点讷? …

STM32通用定时器-输入捕获-脉冲计数

一、知识点 编码器   两相编码器(正交编码器):两相编码器由 A 相和 B 相组成,相位差为 90 度。当旋转方向为顺时针时,A 相先变化,然后 B 相变化;当旋转方向为逆时针时,B 相先变化…