循环队列:一道使数据结构萌新知道什么是“愁滋味“的题目

这破题目肝了我一天半才搞明白,也正是因为这道题目,我才豁然明白了李煜所说的"剪不断,理还乱...别是一般滋味在心头"到底是什么"滋味".在完全搞明白之前,真的是放有放不下,理也理不清...

但是理解之后你会发现,嘛い---,也就那么个回事嘛O(∩_∩)O

目录

1.题目:来自力扣

2.为什么选择数组(顺序表)是实现这道题的最好的方案

3. 有如何判断环状顺序表何种情况下为空,以及何种情况下为满的问题

4.需要实现的操作

5.具体操作的代码实现

5.1创建一个顺序表

5.2判空与判满操作

 5.3队尾加入新元素操作

 5.4队头删除元素操作

5.5显示头操作

5.6重难点:显示尾操作

6.写这条题目时顺便把自己的思路写了一下整理成笔记,分享一下


1.题目:来自力扣

2.为什么选择数组(顺序表)是实现这道题的最好的方案

  1. 简单性和易实现性:循环队列的实现相对简单,主要涉及数组的索引计算和循环移位。而链表的实现需要处理节点的创建、删除和指针操作,相对复杂
  2. 时间复杂度:在大多数情况下,循环队列的入队、出队操作的时间复杂度为O(1),因为只需要计算索引和进行简单的赋值操作。而链表的入队、出队操作可能涉及到节点的创建、删除和指针调整,时间复杂度为O(1)或O(n)。

3. 有如何判断环状顺序表何种情况下为空,以及何种情况下为满的问题

若空:则rear和front⼀定是指向同⼀位置的

若满:因为是循环顺序表(数组)那么理论上rear和front也是 .指向同⼀位置,但是这样便会与判空混淆,是⽆法操作的

这种问题我们称沩「假溢出」

所以,解决此问题的最佳方案便是⽤多额外开辟⼀个空间来解决假溢出问题

为确保队满时rear+1可以指向front,所以每次向队列中添加⼀个元素后rear 要指向当前元素的下⼀个位置,于是便有了rear+=1,然后顺理成章便有了 reart1=front来进⾏判断的代码.

如上图,如果rear到达循环队列最后⼀个位置时, rear=7,rear+1=8,但front =0,这并不符合我们的预期,故⽽我们设了⼀个值K,⽤于表示此循环队列中点共有多少个元素(这其中 包括为了解决假溢出⽽额开辟的空间)

⽤(rare+1)%(k+1)来控制rare范围

ps: k是怎么来的?先⽤malloc开辟整数倍的数组每个元素⼤⼩的空间 此时为k,再realloc对其进⾏扩展⾄(k+1),多⼀个假溢出空间。

4.需要实现的操作

bool myCircularQueueIsFull(MyCircularQueue* obj);//判空
bool myCircularQueueIsEmpty(MyCircularQueue* obj);//判满
MyCircularQueue* myCircularQueueCreate(int k); //初始化
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value);//入队
bool myCircularQueueDeQueue(MyCircularQueue* obj);//删除
int myCircularQueueFront(MyCircularQueue* obj);//显示头
int myCircularQueueRear(MyCircularQueue* obj);//显示尾
void myCircularQueueFree(MyCircularQueue* obj);//释放

5.具体操作的代码实现

5.1创建一个顺序表

typedef struct
{int* a;int front;int rear;int k;
} MyCircularQueue;
//使用malloc函数开辟环状顺序表所需空间
//realloc开辟额外空间结局假溢出问题
MyCircularQueue* myCircularQueueCreate(int k) 
{MyCircularQueue* obj0 = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));MyCircularQueue* obj = (MyCircularQueue*)realloc(obj0->a, (k + 1) * sizeof(MyCircularQueue));obj->front = 0;obj->rear = 0;obj->k = k;return obj;
}

5.2判空与判满操作

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

 5.3队尾加入新元素操作

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

注:rear指向队尾元素的下⼀个位置

问题:循环数组最后⼀个空间是为了解决假栈溢出是不放元素的,如果数组 满了rare指向如图所示位置,再进⾏下⼀次放⼊元素的操作时它不就直接被 if(myCircularQueueIsFull(obj))驳回了 就不存在rare⽐k+1⼤的情况了 为啥 这⾥还要⽤obj->rear = (obj->rear) % obj->k + 1进⾏范围限制呢? 

回答:判断队列是否满和⽤取模限定范围这两个操作是⼆选⼀,但是为了 保证代码的健壮性,所以最好两个都写

 5.4队头删除元素操作

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{if (myCircularQueueIsEmpty(obj)){return false;}free(obj->a[obj->front]);obj->front++;obj->front = (obj->front) % obj->k+1;//要考虑front在尾巴的情况return true;
}

注:如图:front在尾巴时,此时front为7,进⾏⼀次删除操作后,front会变成8,但是 这个循环队列没有下标为8的元素,不在范围内,我们预期的是此时front为0,所以 ⽤取模obj->front = (obj->front) % obj->k+1进⾏范围限制操作

5.5显示头操作

//显示头
int myCircularQueueFront(MyCircularQueue* obj)
{if (myCircularQueueIsEmpty(obj)){return -1;}else{return obj->a[obj->front];}
}

5.6重难点:显示尾操作

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

解析:

因为rear是指向队尾下⼀个位置,所以只有rear-1才是队尾 rear!=0时rear-1是没有任何问题的

但是,如果rear=0时,rear-1=-1,不在这个范围内

所以这个问题要分为rear=0和rear!=0两种情况进⾏分类讨论

1.rear!=0时

直接是(rear-1)%(k+1),当A%B是,如果a[obj->rear - 1] % obj->k+1;

2.rear=0时

按循环链表的逻辑lai讲,rear-1=7,于是乎代数上,我们⽤rear-1+k-1=7, 但是如果rear不是0,⼜会发⽣超出范围的情况,我们可以%(k+1)

如此,将两种情况归纳⼀下,就是 return obj->a[obj->rear - 1 + obj- >k+1] % obj->k+1;

当然,如果嫌这么写太别扭,两种情况也可以⽤if...else语句拆开直⽩地 分情况写

6.写这条题目时顺便把自己的思路写了一下整理成笔记,分享一下

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

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

相关文章

三国野史秘闻翻译视频剪辑 条条爆品 一条视频增粉1w (附888G素材内容)

我将为大家分享一个全新的主题——三国野史秘闻。这个主题本身就充满了趣味性,再加上我们独特的解读,由于粉丝们对此类内容非常热衷,因此很容易在评论区引发热烈讨论,这使得我们的短视频有很大的机会在抖音上走红。 项目 地 址 &…

详解C#之WinForm版利用RichTextBox 制作文本编辑器【附源码】

在Windows应用程序开发中,刚刚介绍了WPF版的利用RichTextBox实现文本编辑器,今天继续推出WinForm版的利用RichTextBox实现文本编辑器。本文利用一个简单的小例子,简述如何在WinForm开发中,利用RichTextBox开发文本编辑器&#xff…

数电票又增新票种 百望云率先推出机动车数电票解决方案

经过两年多的试点推广,数电票工程已经覆盖全国大部分省区市(含计划单列市),随着系统建设的深入,不仅是应用功能逐渐完善,对票种的支持也走向全面。 2023年11月天津市正式开启机动车数电票的开具功能&#x…

SpringBoot自定义注解+反射实现 excel 导入的数据组装及字段校验

在前段时间的开发工作中,接手了一个很简单,很普通的开发任务。 要求实现一个单表的基础数据的批量导入功能。 评估下来,用户每次批量导入的数据量也就几千条,也不大。 是不是很简单,没有骗你们吧。但是呢&#xff0…

TB-03F-Kit 基础AT指令的使用

文章目录 前言一、使用前准备1. 确保TB-03F-Kit已经连接到电脑,并且已经烧录好固件。2. 准备号调试助手,并且电脑上已经安装好了串口驱动3. 打开串口调试助手并复位模组 二、指令介绍三、基础指令1. 准备测试2. AT 测试指令3. ATHELP 查看指令4. ATRST 模…

阻塞队列介绍

阻塞队列 kafka是目前来说性能最好的消息队列服务器,能处理TB级别的数据 作用:点赞、评论时,服务器会自动给某个用户发送通知 kafka是个框架,如果不用框架还要解决类似问题,就要用到阻塞队列 BlockingQueue 阻塞队列就是一个…

AI加速引擎PAI-TorchAcc:整体介绍与性能概述

作者:沈雯婷、黄奕桐、艾宝乐、王昂、李永 1、简介 PAI-TorchAcc(Torch Accelerator)是阿里云人工智能平台开发的Pytorch上的大模型训练加速框架。 PAI-TorchAcc提供了一套基于Pytorch的简洁、易用的接口,无需进行模型转换就可以无缝地接入HuggingFac…

Vue+OpenLayers7入门到实战目录

前言 本篇作为《VueOpenLayers7入门到实战》所有文章的二合一汇总目录,方便查找。 本专栏源码是由OpenLayers7.x版本结合Vue框架编写。 本专栏从Vue搭建脚手架到如何引入OpenLayers7依赖的每一步详细新手教程,再到通过各种入门案例和综合性的实战案例&a…

基于springboot+vue的体育馆管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

已经连接过github远程库,如何再次推送及删除远程库的内容

基于上次将文件推送到已经建好的github远程库上,此篇文章主要介绍如何再次推送文件去直接已经连接过的远程库,以此如何删除远程库中不想要的文件。 一、推送文件到远程库 1.将所需推送的文件拉入本地库所建的文件夹下:{ex:JVM相…

java面试(消息队列MQ)

MQ有什么用?有哪些场景? MQ(MessageQueue)消息队列。队列(FIFO)先进先出的数据结构,消息由生产者发送到MQ,后由消费者对消息进行处理。QQ,微信就是MQ场景。 MQ作用&…

搜索准确性提升 20%,Jina Reranker 成为 RAG 优化的新标杆!

在整合大型语言模型(LLM)到业务流程时,企业经常会遇到一些头疼的问题,比如怎样保持数据时效性、避免幻觉现象,以及如何保护数据安全等等。为了解决这些问题,检索增强生成(RAG)技术应…

盘点国内大厂的10个AI创作工具,看看你都用过哪些?

国内大厂的 AI 创作工具,目前已经非常多了,而且有很多都是大家耳熟能详的。 下面整理了一些,包含 AI 绘画、AI 视频、AI 智能体、AI 大模型等多个方向的国内大厂 AI 创作工具。 发现有几款 AI 工具,还真的非常好用。看看这些 AI…

深入浅出Redis(三):Redis数据的存储、删除以及淘汰

引言 Redis是一款基于键值对的数据结构存储系统,它的特点是基于内存操作、单线程处理命令、IO多路复用模型处理网络请求、键值对存储与简单丰富的数据结构等等 本篇文章不像以往文章围绕Redis某个特点来讲解,而是作为过渡介绍,来说一说Redi…

基于springboot的大型商场应急预案管理系统论文

大型商场应急预案管理系统 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了大型商场应急预案管理系统的开发全过程。通过分析大型商场应急预案管理系统管理的不足,创建了一个计算机管理大型商场应急…

软件测试开发环境、测试环境、准生产环境、生成环境

在一个项目开发到发布的整个过程中,会使用到很多个环境进行测试和运行项目。最基本的开发环境、测试环境、准生产环境、生成环境 一、开发环境 开发环境顾名思义就是我们程序猿自己把项目放到自己的电脑上,配置好以后,跑起来项目&#xff0…

如何器测试IP池的质量?代理IP是怎么在问卷调查中应用的呢?

在数字时代,数据收集和分析变得日益重要,而问卷调查作为一种常见的数据收集工具,其效率和准确性直接影响着研究的可信度和有效性。为了实现这一目标,代理IP在问卷调查中的应用变得愈发关键。本文旨在探讨如何测试IP池的质量&#…

真机测试——关于荣耀Magic UI系列HBuilder真机调试检测不到解决办法

​​​​​出现这种状况怎么办 1、开启USB调试 2、重点来了——我们要选择USB配置,选择音频来源 3、连接OK

vue3基础教程(2)——创建vue3+vite项目

博主个人微信小程序已经上线:【中二少年工具箱】。欢迎搜索试用 正文开始 专栏简介1. 前言2.node版本检测3.创建vue项目 专栏简介 本系列文章由浅入深,从基础知识到实战开发,非常适合入门同学。 零基础读者也能成功由本系列文章入门&#x…

javascript数组排序的方法

目录 基本用法 按照数字大小排序 按照降序排序 按照字符串长度排序 按照对象属性排序 在JavaScript中,数组排序通常使用Array.prototype.sort()方法。这个方法会按照指定的顺序对数组的元素进行排序,并返回排序后的数组。如果未指定比较函数&#x…