看懂循环队列

news2024/9/17 7:28:26

循环队列的设计过程

  • 1.循环队列
  • 2.设计循环队列的逻辑过程
    • 2.1 定义循环队列的数据结构
    • 2.2 初始化队列
    • 2.3 入队操作
    • 2.4. 出队操作
    • 2.5 判断队列状态
    • 2.5 获取队头和队尾的元素
      • 力扣相关题目
      • 完整代码

1.循环队列

  • 循环队列是使用有限数组来模拟队列,与普通的队列不同的是,它允许在到达数组末尾时,通过循环回到数组的开头,从而避免了在队满时无法插入新元素的问题,也避免了在队空时错误地移除元素。它巧妙地管理队头(front)和队尾(rear)指针来重复使用已释放的空间。

2.设计循环队列的逻辑过程

2.1 定义循环队列的数据结构

我们知道队列在内存中时以数组的形式存储元素的,那么在定义结构体时就需要定义一个数组指针来储存数据。常定义以下几个成员

1.数组指针,用于存储队列中的元素。
2.队头指针 head(也称为头指针),指向队头元素的位置。
3.队尾指针 tail(也称为尾指针),指向队尾元素之后的位置。
4. 队列的最大容量 k。
typedef struct {
    int* a;
    int head;
    int tail;//指向尾的下一个 
    int k;
} MyCircularQueue;

2.2 初始化队列

初始化时,队列应该是空的,因此 head和 tail都被设置为0
ps: 为了解决队空和队满的条件问题,在开辟空间时多开辟一个空间,即k+1个

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));

    obj->a = (int*)malloc(sizeof(int)*(k+1));//开辟k+1个空间
    obj->head = 0;
    obj->tail = 0;
    obj->k = k;

    return obj;
}

2.3 入队操作

向队列中添加新元素时,要执行以下步骤:

1.检查队列是否已满。head == tail
2.如果未满,则将新元素添加到 tail所指向的位置,并将 tail增加 1。
3.如果 tai达到了数组的末尾,则将其重置为 0(即绕回到数组的开始位置)。
4.如果队列已满,则不能添加新元素。	(tail + 1)%(k + 1) == head
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;

    obj->a[obj->tail] = value;
    obj->tail++;

    obj->tail %= (obj->k + 1);

    return true;
}

2.4. 出队操作

从队列中移除元素时:

	1.检查队列是否为空。head == tail
	2.如果非空,则将 head指向的元素移除,并将 head增加 1。
	3.如果 head达到了数组的末尾,则将其重置为 0。
	4.如果队列为空,则不能移除元素。
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;

    ++obj->head;

    obj->head %= (obj->k + 1);

    return true;
    
}

2.5 判断队列状态

队空:如果 head== tail并且之前没有元素入队过,则队列为初始状态,即为空。

队满:如果 head== (tail+ 1) % k,则队列已满。

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//队空
    return obj->head == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {//队满
    return (obj->tail + 1) % (obj->k + 1) == obj->head;
}

2.5 获取队头和队尾的元素

获取队头元素:

	1.检查队列是否为空。
	2.如果非空,则返回 head指向的元素。

获取队尾元素:

	1.检查队列是否为空。
	2.如果非空,则返回 tail 指向的前一个位置的元素(因为 tail指向的是队尾元素之后的位置)。
int myCircularQueueFront(MyCircularQueue* obj) {//取队头
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj) {//取队尾
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[(obj->tail - 1 + obj->k + 1) % (obj->k + 1)];
}

力扣相关题目

设计循环队列

完整代码

typedef struct {
    int* a;
    int head;
    int tail;//指向尾的下一个 
    int k;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));

    obj->a = (int*)malloc(sizeof(int)*(k+1));
    obj->head = 0;
    obj->tail = 0;
    obj->k = k;

    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//队空
    return obj->head == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {//队满
    return (obj->tail + 1) % (obj->k + 1) == obj->head;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;

    obj->a[obj->tail] = value;
    obj->tail++;

    obj->tail %= (obj->k + 1);

    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;

    ++obj->head;

    obj->head %= (obj->k + 1);

    return true;
    
}

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

int myCircularQueueRear(MyCircularQueue* obj) {//取队尾
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[(obj->tail - 1 + obj->k + 1) % (obj->k + 1)];
}

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

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

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

相关文章

文献综述在确定先前研究中使用的方法学方法方面发挥什么作用

VersaBot一键生成文献综述 文献综述在确定先前研究中使用的方法学方法方面发挥着至关重要的作用,可以作为设计自己的方法论并证明其重要性的基础。就是这样; 1. 揭示现有方法: 通过探索与您的主题相关的研究,您将发现其他研究人员采用的不同…

普通人有必要学Python吗?学了之后能做什么?

目录 首先来说一下极其推荐的方向: 1、数据分析 2、科学计算 3、大数据框架 4、脚本开发 5、爬虫 6、Web框架 总结: 如果你还没有开始使用Python,答应我,把这个回答看完,如果你真的学习并深入使用过Python&…

锅总浅析虚拟化技术

常见的虚拟化技术有哪些?KVM集群解决方案有哪些?如何用Libvirt操作KVM组成集群?PVE构建虚拟化的特性和其架构又是怎样的?希望完本文,能帮您解答这些疑惑! 一、常见虚拟化技术概述 虚拟化技术是一种通过软…

Qt 实现抽屉效果

1、实现效果和UI设计界面 2、工程目录 3、mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QToolButton> #include <QPushButton> #include <vector> using namespace std;QT_BEGIN_NAMESPACE namespace…

前后端分离开发遵循接口规范-YAPI

目前&#xff0c;网站主流开发方式是前后端分离。因此前后端必须遵循一套统一的规范&#xff0c;才能保证前后端进行正常的数据&#xff08;JSON数据格式&#xff09;请求、影响&#xff0c;这套规范即是 YAPI. 产品经理撰写原型&#xff1b; 前端或后端撰写接口文档。 YAPI…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《计及联盟合作成本的新能源场站共享储能优化配置策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

[Spring] MyBatis操作数据库(进阶)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

功能性的安全保障:输入校验

前言 在软件开发过程中&#xff0c;确保系统的安全性是至关重要的一环。它不仅关乎保护用户数据的完整性和隐私性&#xff0c;也是维护系统稳定运行的基石。我认为&#xff0c;从宏观角度审视&#xff0c;软件开发的安全性保障主要可分为两大类&#xff1a;功能性的安全性保障…

GitEval — 预测你的 GitHub 个人资料的质量

使用机器学习来预测你是否擅长编码 可直接在橱窗里购买&#xff0c;或者到文末领取优惠后购买&#xff1a; 如果你曾经申请过技术职位&#xff0c;你可能已经向公司发送了你的 GitHub 个人资料链接。此个人资料中的信息可以很好地表明你的编码能力以及是否适合团队。所有这些信…

【全国大学生电子设计竞赛】2024年C题

&#x1f970;&#x1f970;全国大学生电子设计大赛学习资料专栏已开启&#xff0c;限时免费&#xff0c;速速收藏~

Opencv画出红底白字标准中文显示框

链接&#xff1a;https://pan.baidu.com/s/1iEJKpqt-z_5yBJdenUABbA 提取码&#xff1a;uoox 先把这个文件拿了&#xff0c;这个文件是一个ttf的字体&#xff0c;用于显示中文。 核心代码&#x1f451; def cv2AddChineseText(self, img_ori, text, p1, box_color, textColo…

【JavaScript】函数声明和函数表达式的区别

文章目录 一、函数声明1. 定义方式2. 作用域提升&#xff08;Hoisting&#xff09;3. 块级作用域 二、函数表达式1. 定义方式2. 作用域提升&#xff08;Hoisting&#xff09;3. 自引用 三、其他区别1. 函数名2. 可读性和代码组织3. 使用场景 四、总结函数声明函数表达式 在Java…

昇思MindSpore学习入门-自动混合精度

混合精度&#xff08;Mix Precision&#xff09;训练是指在训练时&#xff0c;对神经网络不同的运算采用不同的数值精度的运算策略。在神经网络运算中&#xff0c;部分运算对数值精度不敏感&#xff0c;此时使用较低精度可以达到明显的加速效果&#xff08;如conv、matmul等&am…

Android 10.0 Launcher3仿ios的folder文件夹widget功能实现一

1.前言 在10.0的系统ROM开发中,在进行一些系统Launcher3定制功能开发中,需要实现folder文件夹widget的功能,由于launcher3 默认不支持folder跨行显示,所以就需要借助自定义的widget小部件功能来实现相关功能,接下来分析实现相关功能 2.Launcher3仿ios的folder文件夹widge…

【保姆级教程】免费域名注册 Cloudflare 域名解析 Ngnix端口转发

前段时间&#xff0c;带大家搞了两台云服务器&#xff1a; 玩转云服务&#xff1a;Oracle Cloud甲骨文永久免费云服务器注册及配置指南玩转云服务&#xff1a;手把手带你薅一台腾讯云服务器&#xff0c;公网 IP 基于这两台云服务器&#xff0c;我们玩转了很多有趣的开源项目&…

ElasticSearch(八)— 聚集查询1

一、总概 聚集查询(Aggregation)提供了针对多条文档的统计运算功能&#xff0c;它不是针对文档本身内容的检索&#xff0c;而是要将它们聚合到一起运算某些方面的特征值。 聚集查询与 SQL 语言中的聚集函数非常像&#xff0c;聚集函数在 Elasticsearch 中相当于是聚集查询的一…

掌控数据流的智能仪表板:Redpanda Console

Redpanda Console&#xff1a; 一站式管理&#xff0c;让数据流尽在掌控之中。- 精选真开源&#xff0c;释放新价值。 概览 Redpanda Console&#xff0c;是一款创新的Web界面工具&#xff0c;专为简化Kafka和Redpanda数据流的监控与管理而设计。它以用户友好的交互方式&#…

浏览器用户文件夹详解 - Favicons(二)

1. 引言 上一篇文章我们深入探讨了Chromium用户文件夹中的Bookmarks文件,了解了它的JSON结构以及如何解析和修改书签数据。 在本文中,我们将继续探索Chromium用户文件夹中的另一个重要文件:Favicons。Favicons,也就是我们常说的网站图标,是浏览器中不可或缺的一部分。它们不仅…

RK3568笔记四十七:PWM 子系统

若该文为原创文章&#xff0c;转载请注明原文出处。 pwm 子系统功能单一&#xff0c;很少单独使用&#xff0c;一般用于控制显示屏的背光、控制无源蜂鸣器、伺服电机、电压调节等等。 一、PWM介绍 PWM(Pulse width modulation)&#xff0c;脉冲宽度调制。在内核中 PWM 驱动较简…

并发编程工具集——并发容器-下(二十五)

List List 里面只有一个实现类就是 CopyOnWriteArrayList。CopyOnWrite&#xff0c;写的时候会将共享变量新复制一份出来&#xff0c;读操作完全无锁&#xff1b;适合读多写少的场景&#xff0c;写操作会复制数组&#xff0c;在新的数组中操作实现原理&#xff1a;CopyOnWriteA…