速学数据结构 | 循环队列怎么写才最高效?只需要掌握这些技巧

news2024/11/27 4:27:44

在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏:《Linux深造日志》《C++干货基地》

⛺️生活的理想,就是为了理想的生活!

文章目录

  • 📋 前言
  • 一、什么是循环队列?
  • 二、如何实现循环队列?
    • 2.1 循环队列的结构
    • 2.2 循环队列的初始化
    • 2.3 如何检查队列是非为空
    • 2.4 如何检查队列是否满了
    • 2.5 循环队列如何插入数据
    • 2.6 循环队列如何删除数据
    • 2.7 获取循环队列头元素
    • 2.8 获取循环队列尾元素
    • 2.9 如何销毁循环队列
  • 三、循环队列练习
      • 循环队列结构代码:
      • 循环队列练习题
  • 📝全篇总结

📋 前言

  🌈hello! 各位宝子们大家好啊,今天给大家带来循环队列的详细解析,队列我们会写了那么循环队列呢?今天这个还是有点难度的
  ⛳️学完之后保证你对队列又会有一个更清晰的认识。让你彻底拿捏队列循环队列一搞完我们的队列学习就告一段落了。
  📚本期文章收录在《数据结构&算法》,大家有兴趣可以看看呐
  ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!

一、什么是循环队列?

队列我们都自动是数据结构中类似排队一样的结构,主要满足:先进先出的特点。而循环队列的话顾名思义就是把头和尾链接起来循环这样就是循环队列了。

  • 下面我们就来看一下他大概得物理图吧!

在这里插入图片描述

上面是为了方便大家理解而做的图,而实际的循环队列是这样的

在这里插入图片描述

二、如何实现循环队列?

这里我们先看一下力扣上面的题目要求我们,要实现循环队列要实现的功能然后再进行逐个实现就好了。

  • 循环队列链接:622. 设计循环队列
    在这里插入图片描述

2.1 循环队列的结构

首先我们需要考虑的就是循环队列的结构,很多人可就会想到使用链表去实现循环队列但是这里有俩个问题:

  • 循环队列如何判空和满?
  • 如果让 rear 指向有数据的那么插入第一个数据的时候是否为空?
  • 如果让rear 指向数据后面的空间那么 尾元素该如何去找?
  • 如果 rear 满了如何判定是否为空

在这里插入图片描述

所以为了解决这种情况我们选择试用数组的方式实现,多开一个元素来实现循环链表就完美解决问题了:

  • 使用 下标访问 解决找不到前一个元素的问题
  • 而假溢出问题:我们多开了一个空间可以解决空和满的问题

2.2 循环队列的初始化

好了上面我们已经知道了循环队列用哪种方式更优,那么接下来就是设计循环队列的结构了:

  • 首先我们需要一个 int* 的指针来开辟数组
  • 然后需要一个头 front 当下标
  • 需要一个尾 rear 来当尾数据的下一个下标
  • 需要一个 k 来接收开辟队列的长度

📚 代码演示:

ypedef 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;
}

2.3 如何检查队列是非为空

这个就更加简单我们我们前面说了:

  • 只要 front == rear 就为空,因为没有数据俩个都是同一个下标。

📚 代码演示:

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

2.4 如何检查队列是否满了

如何检查队列是否满了,就需要判断一下 rear 的下一个是否为 front 了:

  • 这里需要注意的是 rear 的过界问题,如何让下标回归正常
  • 其实只需要 模除 一下就好了

📚 代码演示:

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

2.5 循环队列如何插入数据

循环队列插入数据的话,首先要判断是否为满就然后插入就行了:

  • 然后 ++obj->rear 了之后要考虑一下 rear 在最后一个位置的情况
  • 模除一下就好了

📚 代码演示:

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

    return true;
}

2.6 循环队列如何删除数据

删除数据也是一样,循环队列如果空了就返回 false 没空 front++ 就好了:

  • 同样要注意控制好front的边界值

📚 代码演示:

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

    
}

2.7 获取循环队列头元素

获取头元素就很简单啦,只需要使用 front 来当下标访问就好了

📚 代码演示:

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

2.8 获取循环队列尾元素

这里就需要考虑很多问题,rear是尾元素的下标的一个一个下标:

  • 我们需要要考虑如果 rear 指向最后一个空间怎么办?
  • rear 指向中间怎么办? 如何回到上一个
  • rear 下标为零的时候 如何回到他的上一个下标

📚 代码演示:

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

2.9 如何销毁循环队列

销毁就很简单了,先 free 掉我们动态开辟的空间,在free掉循环队列的空间就好了:

📚 代码演示:

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

三、循环队列练习

循环队列结构代码:

📚 代码演示:

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

} MyCircularQueue;

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

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

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 myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        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;
    else
        return obj->a[obj->front];
}

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



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

循环队列练习题

这里我们可以去力扣一下检验和练习一下:

  • 这章内容还是比较有难度的,可以多琢磨琢磨
  • 力扣题目链接: 循环队列

在这里插入图片描述

📝全篇总结

☁️ 把本章的内容全部掌握,铁汁们对于队列的理解就更上一层楼了!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
在这里插入图片描述

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

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

相关文章

leetcode:268. 丢失的数字(异或运算)

一、题目 函数原型: int missingNumber(int* nums, int numsSize) 二、思路: 0 - n缺失一个数字,那么将数组中所有的数字按位异或,再按位异或0 - n的所有数字,由于 x ^ x 0,0 ^ x x,因此最终运…

Win10/Win11总是自动更新,如何关闭自动更新?

参考:https://www.zhihu.com/search?q%E5%85%B3%E9%97%ADwindows%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0&search_sourceSuggestion&utm_contentsearch_suggestion&typecontent 手动关闭 1 Windows服务 1.1 WinR输入services.msc打开服务 1.2 找到Windows Update…

黑马程序员项目-黑马点评

黑马点评1 短信登录 基于Session实现登录流程 发送验证码: 用户在提交手机号后,会校验手机号是否合法,如果不合法,则要求用户重新输入手机号 如果手机号合法,后台此时生成对应的验证码,同时将验证码进行…

从MFC初始化过程看rc文件的行为,并剖析关联控件变量的实质

以MFC对话框程序为例: 当我们打开资源编辑器时就可以很容易的添加各种控件窗口,资源编辑器实际上操作的是rc文件;那么这些控件窗口是何时被MFC创建与管理的 没有关联控件变量前,在资源编辑器中依然可以容易拖动控件,并显示出来;这个控件窗口是如何被创建和管理的: 资源编…

【C语法学习】13 - fscanf()函数

文章目录 1 函数原型2 参数3 返回值4 比较5 示例5.1 示例15.2 示例2 1 函数原型 fscanf():从指定流stream读取格式化输入,函数原型如下: int fscanf(FILE *stream, const char *format, ...)2 参数 fscanf()函数参数包括三部分&#xff1a…

Node.js 中解析 HTML 的方法介绍

在 Web 开发中,解析 HTML 是一个常见的任务,特别是当我们需要从网页中提取数据或操作 DOM 时。掌握 Node.js 中解析 HTML 的各种方式,可以大大提高我们提取和处理网页数据的效率。本文将介绍如何在 Node.js 中解析 HTML。 基本概念 HTML 解析…

【广州华锐互动】VR野外求生技能学习,让你感受真实的冒险之旅!

随着科技的迅速发展,虚拟现实(VR)技术为人们提供了一个全新的、身临其境的探险体验。通过将用户带入一个仿真的、沉浸式的虚拟环境,VR互动体验让人们在安全的氛围中感受到野外探险的乐趣。本文将从视觉呈现、沉浸式体验、交互性和应用范围四个方面&#…

MATLAB颜色索引表---持续更新中--各个平台都可使用

MATLAB颜色索引表—持续更新中–各个平台都可使用

探索ChatGPT在学术写作中的应用与心得

随着人工智能的迅猛发展,ChatGPT作为一种强大的自然语言处理模型,逐渐在学术界引起了广泛的关注。本文将探讨ChatGPT在学术写作中的应用,并分享使用ChatGPT进行学术写作时的一些经验和心得。 01 — ChatGPT在学术写作中的应用 1.文献综述和…

【ChatOCR】OCR+LLM定制化关键信息抽取(附开源大语言模型汇总整理)

目录 背景技术方案存在的问题及解决思路关键信息提取结果其他解决方案替换文心一言LangChain大型多模态模型(Large Multimodal Model, LMM) 开源大模型汇总LLaMA —— Meta 大语言模型Stanford Alpaca —— 指令调优的 LLaMA 模型Lit-LLaMA —— 基于 na…

基于单片机的语音存储与回放系统设计

博主主页:单片机辅导设计 博主简介:专注单片机技术领域和毕业设计项目。 主要内容:毕业设计、简历模板、学习资料、技术咨询。 文章目录 主要介绍一、控制系统设计1.1 系统方案设计1.2 系统工作原理 二、硬件电路设计总电路设计图 三、 软件设…

shufflenet v2 yolo

设计理念 1x1卷积进行平衡输入和输出的通道大小;组卷积要谨慎使用,注意分组数;避免网络的碎片化;减少元素级运算。 ShuffleNet v2中弃用了1x1的group convolution操作,而直接使用了input/output channels数目相同的…

win10系统nodejs的安装npm教程

1.在官网下载nodejs,https://nodejs.org/en 2,双击nodejs的安装包 3,点击 next 4,勾选I accpet the terms in…… 5,第4步点击next进入配置安装路径界面 6,点击next,选中Add to PATH ,旁边…

高压检测设备

比如:高压数字表、高压差分探头、指针式高压表、电流探枪、高压探棒 这些设备都是用来测量高压的,有的测电压,有的测电流。 高压数字表: 单独使用,功能很简单,有2个正负极探爪,把2个探爪连接到…

Linux 安装 RocketMq

RocketMq是阿里出品(基于MetaQ)的开源中间件,已捐赠给Apache基金会并成为Apache的顶级项目。基于java语言实现,十万级数据吞吐量,ms级处理速度,分布式架构,功能强大,扩展性强。 官网…

大厂面试题-IO和NIO区别

从下面几个方面来回答: 首先,I/O,指的是IO流,它可以实现数据从磁盘中的读取以及写入。 实际上,除了磁盘以外,内存、网络都可以作为I/O流的数据来源和目的地。 在Java里面,提供了字符流和字节…

http协议 - 常见渗透测试姿势

文章目录 HTTP是什么GET 请求POST请求HEAD请求 HTTP绕过练习靶场修改添加请求头部字段内容绕过referer User-Agent x-forwarded-for进入题目内容(1) 修改添加cookie字段内容绕过cookie进入题目内容(2) 工具: Burp Sui…

NodeJS 安装及环境配置

下载地址:https://nodejs.org/zh-cn/download/ 安装 NodeJS 根据自己电脑系统及位数选择,一般都选择 windows 64位 .msi 格式安装包。 所用命令: node -v npm -v PS:如果以上两条命令都能执行成功,表示安装完成&#…

Compose-Multiplatform在Android和iOS上的实践

本文字数:4680字 预计阅读时间:30分钟 01 简介 之前我们探讨过KMM,即Kotlin Multiplatform Mobile,是Kotlin发布的移动端跨平台框架。当时的结论是KMM提倡将共有的逻辑部分抽出,由KMM封装成Android(Kotlin/JVM)的aar和…

NUUO网络摄像头(NVR)RCE漏洞复现

简介 NUUO Network Video Recorder(NVR)是中国台湾NUUO公司的一款网络视频记录器。 NUUO NVR视频存储管理设备的__debugging_center_utils___.php文件存在未授权远程命令执行漏洞,攻击者可在没有任何权限的情况下通过log参数执行任意命令。…