循坏队列CircularQueue

news2024/11/23 10:29:58

前言

一、CircularQueue

二、特点

三、设计思路

1)判空与判满

2)链表还是数组实现?

四、实现

1).IsEmpty()

2).IsFull()

3)CircularQueueCreate创建

4)CircularQueueEnQueue插入

5)CircularQueueDeQueue删除

6)出队尾和队头

五、总结


前言

循坏队列,本质是队列数据结构。普通队列,入数据时可能会增容,出数据会浪费空间。

因此设计一款循环队列,能够利用队列前的空间。

本文针对循坏队列的优势,循坏队列的思路以及实现进行深入剖析。

一、CircularQueue

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

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

二、特点

优点:

        提前根据需求,开辟相应的空间,不需要后续增容;

        充分地使用数组中的存储空间,克服”假溢出”现象;

缺点:

        固定容量,使用时必须把握是否满容;

三、设计思路

循环队列就是首尾相连的线性结构。

 设计头指针(front)和尾指针(rear)

每次插入数据rear往前走一步,删除数据front往前走一步。如果能合理掌控,那么front和rear能在循坏队列的每一个位置持续走动。、

针对循坏队列,应设计如下接口:

1)判空与判满

判空:
front==rear时,标记为空。

判满:

因为front==rear表示空,那么判满就不能用front==rear.

        设计:

             1.增加一个size变量,每次存数据size就++。用size来判断是否满

             2.rear+1=front

             每次存入一个元素rear就往前走一步,rear在最后一个元素的下个位置。当     rear+1==front时,判断满。因此在设计队列的容量时,多开辟一个空间。

下图表示一个容量大小为7的循环队列满时的情况

2)链表还是数组实现?

链式结构,首尾可以轻松链接.

但是在创建循环队列时,链接多个结点,过于麻烦。

出尾部数据麻烦:

        改进思路:1.添加rearprev指针  2.遍历一遍队列  3.双向循坏链表

不难发现,链表实现还是比较麻烦的。本文将介绍数组实现循环队列。

四、实现

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

1).IsEmpty()

rear==front

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

    return false;
}

2).IsFull()

分俩种情况,

1.rear+1不会溢出

 rear+1==front 判满

2.rear+1溢出

 此时为空,但是rear+1!=front 

则需要对rear+1取模

(rear+1)%(k+1)==front

为什么模上k+1而不是k :因为开辟空间是k+1,相当于长度是k+1。例如上述k为5,rear此时为5  

(5+1)%(5+1)=0  刚好为front的下标 判断成立。

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

3)CircularQueueCreate创建

循环队列的创建

先创建obj队列指针,再对数组开辟空间,注意空间大小是K+1

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

4)CircularQueueEnQueue插入

要插入先检查是否为满

插入的位置为rear,每次插入后rear往后走一步,但是rear会存在溢出,所以每次插入都对rear取模

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

5)CircularQueueDeQueue删除

要检查是否为空

每次删除,front往前走一步就可

front会存在溢出,同4)需对front取模

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

6)出队尾和队头

特别注意的是,当rear位于第一个位置时,如下

rear-1为非法值,需要将rear移到最后一个位置上

这里提供一个巧妙的方法:
将rear+k+1,相当于容量变成二倍,rear往后移动一个容量的长度

rear+k+1-1(rear+k)就实现将rear移到最后一位上

如果rear不在第一个位置,那么需要对rear+k取模

 

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

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

五、总结

循环队列因为其可重复利用空间而受到推崇,在判满和出队尾数据时需要注意rear的不同

本文详细讲解每个细节,希望对大家有所帮助!

编程学习没有捷径,要多写多练,感谢阅读。

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

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

相关文章

React Hook之useCallback 性能优化

上文 对比之前的组件优化说明React.memo的作用我们说了 React.memo的妙用 但是 它却并非万能 我们来看这个情况 我们子组件代码编写如下 import React from "react";const ChildComponent ({ dom1funt }) > {console.log("ChildComponent 被重新渲染"…

规则引擎--规则集:规则集合的组织和执行

目录 回顾easy-rules的rules执行如何想规则集合的构造 规则集合定义普通规则集和执行定义树形规则集 当弄清楚了一个规则的设计和执行逻辑后,接下来需要考虑的就是许多的规则如何组织了,即规则集的抽象设计。 来看一些例子 回顾easy-rules的rules执行 …

NFCEE Discovery and Mode Set

10.1 NFCEE ID NFCC 动态为 NFCEE 分配 ID(称为“NFCEE ID”)。 DH 通过执行 NFCEE Discovery 来了解 ID 值。 在配置状态为 0x01 的 NFCC 重置之前,NFCEE ID 一直有效。 值为 0x00 的 ID 在本规范中称为 DH-NFCEE ID,并且应代表…

五、Docker本地镜像发布到阿里云/发布到私有库

目录 前言一、本地镜像发布到阿里云1.1 流程图1.2 注册阿里云创建容器服务个人实例1.3 创建命名空间1.4 创建镜像仓库1.5 将镜像推送到阿里云本地仓库 二、从阿里云仓库拉去自己推送的镜像三、本地镜像发布到阿里云总结四、本地镜像发布到私有库4.1 流程图4.2 下载镜像Docker R…

Shell编程从入门到实践——实践篇

欢迎关注 「Android茶话会」 回 「学习之路」 取Android技术路线经典电子书回 「pdf」 取阿里&字节经典面试题、Android、算法、Java等系列武功秘籍。回 「天涯」 取天涯论坛200精彩博文,包括小说、玄学等 背景 之前在搞一些CI/CD,使用到了shell脚本,shell的开…

nvdiffrec在Windows上的配置及使用

nvdiffrec是NVIDIA研究院开源的项目,源代码地址:https://github.com/NVlabs/nvdiffrec ,论文为《Extracting Triangular 3D Models, Materials, and Lighting From Images》,从图像中提取三角形三维(三角网格)模型、空间变化的材质…

uni-app微信小程序获取手机号授权登录(复制即用,js完成敏感数据对称解密,无需走服务端处理)

目录 一、示例 二、具体实现说明 一、示例 获取到的手机号 二、具体实现说明 属性说明 属性名说明生效时机getphonenumber获取用户手机号回调open-type"getPhoneNumber" 按钮写法 <template><view class"login"><view class"content…

为什么要写这个带点玄幻气息的英语单词记忆博客

&#x1f31f;博主&#xff1a;命运之光 ☀️专栏&#xff1a;英之剑法&#x1f5e1; ❤️‍&#x1f525;专栏&#xff1a;英之试炼&#x1f525; ☀️博主的其他文章&#xff1a;点击进入博主的主页 &#x1f433; 开篇想说的话&#xff1a;开学就大三了&#xff0c;命运之光…

DMA详解及应用(嵌入式学习)

DMA 0. 前言1. DMA作用2. DMA特性3. DMA寄存器4. DMA的增量或者循环模式5. 练习 0. 前言 DMA&#xff08;Direct Memory Access&#xff0c;直接内存访问&#xff09;是一种计算机系统中用于高效地实现数据传输的技术。它允许数据在外设和内存之间直接传输&#xff0c;而无需C…

GEE:为每个对象(斑块/超像素)添加属性

作者:CSDN @ _养乐多_ 本文将介绍为每个对象(斑块/超像素)添加属性的代码。并举例将最近距离作为属性添加到每个对象(斑块/超像素)特征中。 结果如下图所示, 文章目录 一、代码二、代码链接一、代码 这段代码的目的是对动态世界土地覆盖图像进行分析,并提取出其中的目…

贪婪算法简介-数据结构和算法教程

贪婪算法是一种算法范例&#xff0c;它遵循在每个阶段进行局部最优选择的问题求解启发式&#xff0c;希望找到全局最优值。换句话说&#xff0c;贪婪算法在每一步都选择最好的可能选项&#xff0c;而不考虑该选择对未来步骤的影响。 当一个问题可以被划分成更小的子问题&#…

1.GPIO的工作原理

1.stm32引脚说明&#xff1a; 对于stm32f103zet6&#xff1a; 一共有7组io口&#xff1b;每组io口有16个io&#xff1b;一共有16*7112个io&#xff1b;分组情况为&#xff1a;GPIOA&#xff0c;GPIOB~GPIOG&#xff1b; 2.GPIO的基本结构&#xff1a; 3.GPIO的工作模式&…

C++入门:类和对象(后)

目录 前言&#xff1a; 一&#xff1a;static成员 (1)概念 (2)特性 (3)例子 二&#xff1a;explicit关键字 三&#xff1a;内部类 (1)概念 (2)特性 (3)实例 四&#xff1a;匿名对象 (1)概念 (2)特性 (3)实例 五&#xff1a;拷贝对象时的一些编译器优化 (1)引入 …

Spring整合MyBatis底层原理

Spring整合MyBatis底层原理 项目结构图 项目代码 build.gradle需要进入的依赖 // testImplementation(platform("org.junit:junit-bom:5.9.1")) // testImplementation("org.junit.jupiter:junit-jupiter")implementation("org.aspectj:aspect…

电池SOC和动力电池OCV功率联合估计研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

爱心方程(理科生的浪漫?)

目录 前言 C/C 源代码 扩展 Java Python HTML 前言 这个在大一的时候就想找了&#xff0c;然后后面是找到了一个&#xff0c;但是忘记出处了。我决定把可以找到的所有爱心给整理一下&#xff0c;为了实现“理科生的浪漫”&#xff01;&#xff01;&#xff01; C/C 首先…

你认为年轻人存款难吗?难啊难,难如上青天!!!

近日&#xff0c;有调查称“大概五分之一的年轻人存款在一万元以内。10万元存款是一个“坎”&#xff0c;存款超过10万就会超过53.7%的人。”“年轻人”“存款”两个词碰撞在一起&#xff0c;引来了广泛的关注和讨论。你认为年轻人存款难吗&#xff1f;可以从以下几个角度发表你…

Linux Nacos 设置systemctl service 并添加为开机启动

为方便在启动服务器时&#xff0c;不需要一个一个手动启动服务&#xff0c;需要把nacos设置为开机启动。方法如下&#xff1a; 在/usr/lib/systemd/system 目录下面添加nacos.service脚本&#xff1a; # 下面这一行必须有&#xff0c;不然会报错 #vim /usr/lib/systemd/system…

libevent(3)IO模型基础知识

一、用户态和内核态 我们知道现在的操作系统是分层的&#xff0c;内核封装了与底层的接口&#xff0c;通过系统调用提供给上层应用使用。 当进程运行在内核空间时&#xff0c;它就处于内核态&#xff1b;当进程运行在用户空间时&#xff0c;它就处于用户态。 当我们需要进行IO操…

【小沐学Python】网络爬虫之requests

文章目录 1、简介2、requests方法2.1 get2.2 post 3、requests响应信息4、requests的get方法4.1 url4.2 headers4.3 params4.4 proxies4.5 verify4.6 timeout4.7 cookies4.8 身份验证 3、测试代码3.1 获取网页HTML&#xff08;get&#xff09;3.2 获取网页HTML&#xff08;带he…