循环队列详解

1. 循环队列

1.1 概念及结构

循环队列是一种特殊类型的队列数据结构,也被称为”唤醒缓冲器“。它在数组的基础上实现了循环利用空间的功能。在循环队列中,队尾和队头之间形成了一个循环,当队尾指针“追上”队头指针时,队列不再继续增长,而是继续利用之前出队的空间。

循环队列通常由两个指针来辅助构建:

  1. 队尾指针(rear):指向队尾元素的下一个位置,也就是即将插入新元素的位置。
  2. 队头指针(front):指向队头元素的位置

入队和出队:

  • 入队操作会将元素插入到队尾指针所指向的位置,并将队尾指针后移。当队列满时,入队操作会失败。

  • 出队操作会**删除队头元素,并将队头指针后移。**当队列为空时,出队操作会失败。

队空和队满的条件:

  • 当队列为空时,front指针和rear指针同时指向下标为0的位置,因此循环队列为空的条件为front == rear
  • 需要清楚,由于循环队列需要预留一个空间来区分队列为空和队列满的状态队列满的条件为rear + 1 == head

为什么需要预留一个空间?

假设我们不预留空间,要对下面的队列插入元素‘7’

那么插入后,front(head)rear(tail)两个指针的关系就变成了这样:

可以看到,frontrear又相等了,这不就和队列为空的条件混到一起了吗。所以说要多预留一个空间用来判断队列满的情况:

1.2 结构的定义

这里我们用数组来模拟实现循环队列

typedef struct {
    int *data;	//动态数组
    int front;	//队头指针
    int rear;	//队尾指针
    int capacity;	//最大容量
} MyCircularQueue

1.3 基本功能实现

1.3.1 初始化(返回一个循环队列指针)

MyCircularQueue* myCircularQueueCreate(int k);
  • k为循环队列的最大容量
  • 该函数用来返回一个已经初始化好的循环队列指针
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* CQueue = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    
    CQueue->data = (int*)malloc(sizeof(int) * (k + 1));	//申请k+1个空间
    CQueue->front = 0;
    CQueue->rear = 0;
    CQueue->capacity = k;

    return CQueue;
}

1.3.2 判空

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

1.3.3 判满

可不要简单的以为循环队列满的条件就是rear + 1 == front,我们要考虑下面两种情况(假设最大容量为4):

情况一:

情况二:

上面两种情况队列都是满的,显然我们不能简单的用front == rear + 1来判断队列是否已满。

直接下结论:我们可以用表达式**(rearf + 1) % capacity == front**来判断队列是否已满

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

1.3.4 入队

入队移动的是队尾指着,同样也要考虑两种情况:

情况一:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vIYd7ryM-1691591491729)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230809090716043.png)]

情况二:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A4WZgZn3-1691591491730)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230808114647693.png)]

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj))	//如果已满,插入失败
        return false;

    //如果队尾指针在队列尾部,那么插入过后,队尾指针移到最前面
    if (obj->rear == obj->capacity)
    {
        obj->data[obj->rear] = value;
        obj->rear = 0;
    }
    //否则队尾指针加以即可
    else
    {
        obj->data[obj->rear] = value;
        obj->rear++;
    }

    return true;
}

1.3.5 出队

出队移动的是队头指针,考虑两种情况:

情况一:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i819wqgc-1691591491730)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230809091122868.png)]

情况二:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NmLHjGvL-1691591491731)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230809091358771.png)]

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))	//如果队列为空,则出队失败
        return false;

    //如果队头指针位于队列最后一个位置,那么删除后就要回到最前面
    if (obj->front == obj->capacity)
        obj->front = 0;
    //否则队头指针往后移即可
    else    
        obj->front++;

    return true;
}

1.3.5 返回队头元素

由于队头指针指向的就是队头元素,因此直接返回下标位置的元素即可

int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))	//队列为空,返回-1
        return -1;

    return obj->data[obj->front];
}

1.3.6 返回队尾元素

由于队尾指针指向的是队尾元素的下一个位置,因此要考虑两种情况:

情况一:

情况二:

int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))	//队列为空,返回-1
        return -1;

    //如果队尾指针在下标为0的位置,就说明队尾元素位于数组最后的位置
    if (obj->rear == 0)
        return obj->data[obj->capacity];
    //否则,队尾元素就是队尾指针下标-1的位置
    else
        return obj->data[obj->rear - 1];
}

1.3.7 销毁队列

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->data);	//销毁数组
    free(obj);	//销毁队列
}

1.4 练习

学习完循环队列的相关知识,可以做这一题来加深印象👉设计循环队列

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenAI允许网站阻止其网络爬虫;谷歌推出类似Grammarly的语法检查功能

🦉 AI新闻 🚀 OpenAI推出新功能,允许网站阻止其网络爬虫抓取数据训练GPT模型 摘要:OpenAI最近推出了一个新功能,允许网站阻止其网络爬虫从其网站上抓取数据训练GPT模型。该功能通过在网站的Robots.txt文件中禁止GPTB…

【前端 | CSS】flex布局

基本概念 Flexible模型,通常被称为 flexbox,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的空间分布和对齐能力 我们说 flexbox 是一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者…

vscode运行python报错:ModuleNotFoundError:No module named ‘xxx‘

在乌班图上使用pycharm的时候,pycharm总是莫名其妙卡死,又说是搜狗输入法的锅,又说别的原因,一气之下不用pycharm,转到vscode上,没想到出现了如下报错。 就是vscode在运行python的时候,自定义模块的调用无…

03.利用Redis实现缓存功能---解决缓存穿透版

学习目标&#xff1a; 提示&#xff1a;学习如何利用Redis实现添加缓存功能解决缓存穿透版 学习产出&#xff1a; 缓存穿透讲解图&#xff1a; 解决方案&#xff1a; 采用缓存空对象采用布隆过滤器 解决方案流程图&#xff1a; 1. 准备pom环境 <dependency><gro…

Redis储存结构

Redis怎么储存的 这个redisDb是数据库对象 里面的其他字段忽略了 然后里面有个dict列表(字典列表) 我们随便来看一个redisObject 区分一下子啊 他这个dict里面没有存redisObject的对象 也没有存dict对象 它只是存了个数据指针 你看那个redis每个底层编码 抠搜的 这块要是再保存…

gin和gorm框架安装

理论上只要这两句命令 go get -u gorm.io/gorm go get -u github.com/gin-gonic/gin然而却出现了问题 貌似是代理问题&#xff0c;加上一条命令 go env -w GOPROXYhttps://goproxy.cn,direct 可以成功安装 安装gorm的数据库驱动程序 go get -u gorm.io/driver/mysql

完整版:TCP、UDP报文格式

目录 TCP报文格式 报文格式 报文示例 UDP报文格式 报文格式 报文示例 TCP报文格式 报文格式 图1 TCP首部格式 字段长度含义Source Port16比特源端口&#xff0c;标识哪个应用程序发送。Destination Port16比特目的端口&#xff0c;标识哪个应用程序接收。Sequence Numb…

【Linux 网络】NAT技术——缓解IPv4地址不足

NAT技术 NAT 技术背景NAT IP转换过程NAPTNAT 技术的缺陷 NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;技术&#xff0c;是解决IP地址不足的主要手段&#xff0c;并且能够有效地避免来自网络外部的攻击&#xff0c;隐藏并保护网络内部的计算…

Ansible从入门到精通【六】

大家好&#xff0c;我是早九晚十二&#xff0c;目前是做运维相关的工作。写博客是为了积累&#xff0c;希望大家一起进步&#xff01; 我的主页&#xff1a;早九晚十二 专栏名称&#xff1a;Ansible从入门到精通 立志成为ansible大佬 ansible templates 模板&#xff08;templa…

【JAVA】七大排序算法(图解)

稳定性&#xff1a; 待排序的序列中若存在值相同的元素&#xff0c;经过排序之后&#xff0c;相等元素的先后顺序不发生改变&#xff0c;称为排序的稳定性。 思维导图&#xff1a; &#xff08;排序名称后面蓝色字体为时间复杂度和稳定性&#xff09; 1.直接插入排序 核心思…

ASL国产CS5213 转VGA信号输出音频 替代AG6200安格芯片 HDMI to VGA(带音频)方案设计原理图

CS5213功能&#xff1a;HDMI转VGA带音频输出&#xff0c;专注于设计HDMI转VGA带音频输出。可替代AG6200 AG6201。 CS5213芯片是一个HDMI&#xff08;高清多媒体接口&#xff09;到VGA桥接芯片。 它将HDMI信号转换为标准VGA信号它可以在适配器、智能电缆等设备中设计。 Capst…

基于MATLAB小波变换的信号突变点检测

之前在不经意间也有接触过求突变点的问题。在我看来&#xff0c;与其说是求突变点&#xff0c;不如说是我们常常玩的"找不同"。给你两幅图像&#xff0c;让你找出两个图像中不同的地方&#xff0c;我认为这其实也是找突变点在生活中的应用之一吧。回到找突变点位置上…

virt-manager上安装ubuntu22.04虚拟机

文章目录 前言一、镜像下载二、 virt-manager新建机器2.1 选择安装来源类型2.2 选择ISO文件2.3 设置CPU数量和内存容量2.4 设置硬盘容量2.5 设置虚拟机类型&#xff0c;勾选配置按钮2.6 修改硬盘驱动类型2.7 修改网卡驱动类型2.8 设置显示器类型2.9 开始安装 三、操作系统安装3…

idea找不到DataBase

一、我想把数据库跟我的idea链接&#xff0c;结果发现找不到。如图。 二、解决方案 找到 file ---setting 找到plugin------找到marketplace 我的已经出现了

.NET根据类的值进行序列化反序列化操作

前言&#xff1a; 在.NET种&#xff0c;序列化一般常用的方式是使用Newtonsoft.Json进行序列化和反序列化操作&#xff0c;比如创建一个Person类 public class Person {public string Name { get; set; }public int Age { get; set; } }序列化为json // 对象序列化为 JSONPe…

Python-OpenCV中的图像处理-图像平滑

Python-OpenCV中的图像处理-图像平滑 图像平滑平均滤波高斯模糊中值模糊双边滤波 图像平滑 使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分&#xff08;比如&#xff1a;噪音&#xff0c;边界&#xff09;。所以边界也会被模糊…

stm32常见数据类型

stm32的数据类型的字节长度 s8 占用1个byte&#xff0c;数据范围 -2^7 到 (2^7-1) s16 占用2个byte&#xff0c;数据范围 -2^15 到 (2^15-1) s32 占用 4个byte&#xff0c;数据范围 -2^31 到 (231-1)231 2147483647 int64_t占用8个byte&#xff0c;数据范围 -2^63 到 (2^63-1)…

【cs61b】学习笔记day2

历史文章目录 【cs61b】学习笔记day1 文章目录 历史文章目录List两个小问题bits声明一个变量引用类型方框和指针表示法数组的实例化链表 SLList List 两个小问题 思考下面两个代码分别输出什么 Walrus a new Walrus(1000, 8.3); Walrus b; b a; b.weight 5; System.out.…

43.字符串相乘

目录 一、题目 二、代码 一、题目 43. 字符串相乘 - 力扣&#xff08;LeetCode&#xff09; 二、代码 class Solution { public: string addStrings(string num1, string num2)//求两个字符串相加 {int end1 num1.size() - 1;int end2 num2.size() - 1;int next 0;//进位…

windows 10 远程桌面配置

1. 修改远程桌面端口&#xff08;3389&#xff09; 打开注册表&#xff08;winr&#xff09;, 输入regedit 找到配置项【计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Terminal Server\Wds\rdpwd\Tds\tcp】 &#xff0c; 可以通过搜索“Wds”快速定位。 修改端口配…