当前位置: 首页 > news >正文

队列概念|循环队列的实现

前言

今天我们将学习循环队列实现,我们首先介绍队列的概念和结构,之后一步步讲解循环队列由来与实现。

一、队列的概念与结构

1、队列的概念

队列: 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。队列是一种先进先出FIFO(first in first out)的线性表,允许插入的一端称为队尾,允许删除的一端称为队头。(这种结构很符合我们生活中的习惯,排在第一个的优先出列,最后来的当然就在队伍最后。)

2、队列的结构

在这里插入图片描述

3、实例

比如: ①键盘的输入:输入“abc”,输出也是“abc”;②生活中的排队等等。

二、循环队列

1、队列的实现方式有两种

线性表有顺序存储和链式存储。同样,队列作为一种特殊的线性表,也同样存在这两种存储方式。

2、队列顺序存储的不足

队列的顺序存储其实就是使用数组来实现。数组实现队列,一般数组下标为0的一端为队头,数组尾为队尾。

入队: 入队是在队尾插入数据,即在数组尾追加一个数据,不需要移动数据,所以时间复杂度为O(1)。如下图:

在这里插入图片描述

出队: 出队是在队头删除数据,即数组的头删,需要挪动后面的所有元素,保证所有元素都从队头出去,此时时间复杂度为O(N)。如下图:

在这里插入图片描述

但是每一次出队列都需要挪动数据,效率不太好。那能不能不将队头的位置固定在下标为0的位置,即每出队列一次,队头向后跳过一个元素,此时时间复杂度为O(1)。如下图:

在这里插入图片描述

使用这种方法出队列,虽然效率提高了,但又引出了一个新问题——“假溢出”。

假溢出: 如下图,假设队列的总个数为5,当数组末尾的空间已经被占用了,此时再入队,就会产生数组越界的问题,可实际上,我们队列在下标0、1、2的地方还是空闲的。这种现象就叫做“假溢出”。

在这里插入图片描述

那“假溢出”有没有解决方案呢?

答案是:有的,有三种解决方案。

①当队列满了,就扩容。但缺点就是空间利用率低。

②不改变队头的位置,挪动数据。缺点:时间复杂度为O(N)。

③循环队列。优点:效率高。(缺点实在来说就只有,队列大小实现前要确定好。)

3、循环队列的定义

循环队列: 我们把队头与队尾是相互链接的队列称为循环队列。因为循环队列首尾相连,所以只要队列没有满就可以插入数据,不会产生假溢出问题。

理解: ①队列的大小要事先确定;②队列首尾相连。

实现:①顺序存储实现;②链式存储实现。这两种实现方式哪种更好呢?

答案是:顺序存储实现更好。假设队列大小为5,队首指针为front,队尾指针的下一个为rear,分析如下:

①链式存储实现:

问题1:队列空与队列满情况一样,如下图:

在这里插入图片描述
解决方案:

①队列成员加一个成员size变量储存有效数据个数——>队列满:size == k;队列空:size == 0。

②队列多开辟一个空间——>队列满:rear->next == front;队列空:rear == front。(这里我们使用方案2解决。)

问题2:取队尾元素不好取,如下图:

在这里插入图片描述
解决方案:①双向链表;②队列加一个成员变量prev储存rear的前驱结点。

②顺序存储实现:

问题1:怎么实现首尾相连,即rear与front到了下标k的位置怎么回到下标0的位置。

在这里插入图片描述
tip:

①取队尾:(rear - 1 + k + 1)% (k + 1)

在这里插入图片描述
②队列满:(rear + 1)% (k + 1)== front,队列空:rear == front

在这里插入图片描述
总结: 由上分析可知,链式存储对比顺序存储的劣势有:①多一个指针域,浪费空间;②不好找队尾元素;③代码实现复杂等等。所以下面我们将使用顺序存储实现循环队列。

4、循环队列的实现

队列的实现,应该支持如下操作:

  • MyCircularQueue(k):构造器,在堆区申请队列对象,初始化队首、队尾指针、队列长度。
  • Front:获取队首元素。如果队列为空,返回-1。
  • Rear:获取队尾元素。如果队列为空,返回-1。
  • enQueue(value):入队列——队尾插入一个元素。如果成功插入返回真。
  • deQueue():出队列——队头删除元素。如果成功删除返回真。
  • isEmpty():检查队列是否为空。
  • isFull():检查队列是否已满。
  • Free():销毁队列。

循环队列在力扣有题目,大家可以先去做一做。链接在下面。

循环队列链接

循环队列的代码实现:

//循环队列的结构
typedef struct 
{int* a;//指向堆区开辟的数组int front;//队首指针——表示队首位置int rear;//队尾指针——表示队尾的下一个int length;//队列长度
} MyCircularQueue;//初始化——在堆区开辟队列对象与队列空间,并初始化队首与队尾,队列长度
MyCircularQueue* myCircularQueueCreate(int k) 
{//在堆区开辟循环队列的对象MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//判断是否开辟成功if(NULL == obj){//打印错误信息perror("malloc fail");return NULL;}//申请队列空间——为避免队列满与空情况一样,队列多开辟一个空间obj->a = (int*)malloc(sizeof(int) * (k + 1));//判断是否开辟成功if(NULL == obj){//打印错误信息perror("malloc fail");return NULL;}//初始化队首、队尾指针obj->front = 0;obj->rear = 0;//初始化队列长度obj->length = k + 1;//返回在堆区开辟循环队列对象return obj;
}
//检查队列是否已满,满返回真
bool myCircularQueueIsFull(MyCircularQueue* obj) 
{//断言obj不为空assert(obj);//相等则满return (obj->rear + 1) % obj->length == obj->front;
}//入队列:队尾插入数据,成功返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{assert(obj);//调用myCircularQueueIsFull判断队列是否满if(myCircularQueueIsFull(obj)){return false;//满,直接返回假}//队尾插入数据obj->a[obj->rear] = value;//插入之后,rear+1obj->rear++;//rear每一次+1后,防止越界,当rear = k时,取模回到下标0obj->rear %= obj->length;//插入成功返回真return true;
}
//检查队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{assert(obj);//相等队列为空return obj->rear == obj->front;
}
//出队列:队头出队列,即front++,出队列成功返回真
bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{assert(obj);//调用myCircularQueueIsEmpty判断队列是否为空if(myCircularQueueIsEmpty(obj)){return false;}//删除队头,即front++obj->front++;//front每一次+1后,防止越界,即当front = k时,取模回到下标0obj->front %= obj->length;//出队列成功返回真return true;
}
//获取队首元素。如果队列为空,返回 -1 。
int myCircularQueueFront(MyCircularQueue* obj) 
{assert(obj);//调用myCircularQueueIsEmpty判断队列是否为空if(myCircularQueueIsEmpty(obj)){//为空,返回-1return -1;}//不为空返回队首元素return obj->a[obj->front];
}
//获取队尾元素。如果队列为空,返回 -1 。
int myCircularQueueRear(MyCircularQueue* obj) 
{assert(obj);//调用myCircularQueueIsEmpty判断队列是否为空if(myCircularQueueIsEmpty(obj)){//为空,返回-1return -1;}//返回队尾元素,rear为队尾的下一个,(rear - 1 + obj->length) % obj->length)即为队尾位置,注意不能使用--操作符return obj->a[(obj->rear - 1 + obj->length) % obj->length];
}
//销毁队列
void myCircularQueueFree(MyCircularQueue* obj) 
{assert(obj);//注意销毁的顺序,要先释放队列结构中的数组,再释放队列对象free(obj->a);//free之后,obj->a指向不变,防止野指针,置为空obj->a = NULL;free(obj);obj = NULL;
}

希望对大家有帮助,循环队列就讲解完成了。循环队列有个缺点就是必须先开辟队列空间,队列的大小实现就要确定好,那有没有队列空间按需提供的呢?答案是:有的,就是链式队列。在下一期作者会对其详细讲解。

相关文章:

队列概念|循环队列的实现

前言 今天我们将学习循环队列实现,我们首先介绍队列的概念和结构,之后一步步讲解循环队列由来与实现。 一、队列的概念与结构 1、队列的概念 队列: 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。队列是…...

监控数据控中的数据表

背景: 在做一个项目的时候,每次代码分析的数据会写入到数据库,目前想实现当数据插入到数据库后,对新插入的数据进行监控解析。当有一个新纪录插入到数据表的时候,数据库可以自动解析新插入的数据记录。 思路如下&…...

进程替换..

1、单进程版 – 最简单的先看看程序替换 现象就是 1、我们用自己的进程封装了内置指令ls,并且代码中execl 后 printf 的after并没有打印出来。 2、谈进程替换的原理 单进程替换基本原理 上面例子中execl的做法非常简单粗暴,要调用ls,那么就把mycom…...

M1安装OpenPLC Editor

下载OpenPLC Editor for macOS.zip文件后,使用tar -zvxf命令解压,然后将"OpenPLC Editor"拖入到"应用程序"文件夹 右键点击"OpenPLC Editor",打开这个""文件,替换为以下内容 #!/bin/bash…...

STM32F10xx 存储器和总线架构

一、系统架构 在小容量、中容量和大容量产品 中,主系统由以下部分构成: 四个驱动单元 : Cotex-M3内核、DCode总线(D-bus)和系统总线(S-bus) 通用DMA1和通用DMA2 四个被动单元 内部SRAM 内部…...

并发编程

什么是并发编程? 并行:在同一个时间节点上,多个线程同时执行(是真正意义上的同时执行) 并发:一个时间段内,多个线程依次执行。 并发编程:在例如买票、抢购、秒杀等等场景下,有大量的请求访问…...

Lauterbach使用指南之RunTime功能

Lauterbach使用指南之RunTime功能 前言 首先,请问大家几个小小问题,你清楚: Lauterbach这个工具是干什么用的吗?在软件运行过程中如何测量两个运行point之间的runtime时间呢?Lauterbach的RunTime功能具体应当如何来操…...

GaussDB数据库管理系统介绍

1.GaussDB的发展 2.GaussDB的生态 内部: 云化自动化方案。通过数据库运行基础设施的云化将DBA(数据库管理员)和运维人员的日常工作 自动化。外部: 采用与数据库周边生态伙伴对接与认证的生态连接融合方案,解决开发者/DBA难获取、应用难对接等…...

使用docker部署lnmp多站点

1. 创建一个 Docker 网络 以便容器可以在同一网络上进行通信 docker network create lnmpnetwork2. 运行 MySQL 容器: 运行 MySQL 容器并将其连接到创建的网络。确保将 MySQL 的端口映射到宿主机上,以便您可以从宿主机访问数据库。 将mysql的配置和数…...

实例详解:Java使用JWT和Redis实现高效单点登录(SSO)

前言 单点登录(Single Sign-On,简称SSO)是一种身份验证和访问控制机制,允许用户使用一组凭证(如登录名和密码)登录到多个应用程序中,而无需为每个应用程序单独进行身份验证。用户只需要登录一次…...

SQL中使用ROLLUP和CUBE函数轻松生成汇总行

在数据分析和报表制作中,通常需要对数据进行汇总和分组,我们常用的就是GROUP BY汇总数据,当我们想按照不同维度汇总时,往往需要编写多个GROUP BY预计,而借助ROLLUP 和 CUBE 函数可以一次性生成子总计和总计行&#xff…...

CentOS 7 安装和配置java环境

1 安装包准备 安装包可以通过下面地址进行版本选择安装: https://www.oracle.com/java/technologies/downloads/#java8 2 正式开始安装 本次分享的安装方法直接通过编辑/etc/profile文件实现java的安装 2.1 新建安装包存放目录 mkdir /java cd /java/ 2.2 解压安…...

「实验记录」CS144 Lab0 networking warmup

文章目录 一、Motivation二、SolutionsS1 - Writing webgetS2 - An in-memory reliable byte stream 三、Results四、Source 一、Motivation 第一个小测试 webget 是想让我们体验并模拟一下在浏览器中键入 URL 后获得远程服务器传来的内容,这并没有太大的难度&…...

html5怎么实现语音搜索

html5怎么实现语音搜索 谷歌的网站在他们首页发现了HTML5的新玩法——语音搜索。 注意&#xff1a; 只有webkit核心的浏览器才能使用 用法很简单 只需要在input添加属性x-webkit-speech即可&#xff0c;例子如下&#xff1a; 代码如下: <input type"text" x-…...

吴恩达《机器学习》1-2:什么是机器学习?

一、什么是机器学习&#xff1f; Arthur Samuel&#xff08;1959&#xff09;&#xff1a; 他定义机器学习为&#xff0c;在进行特定编程的情况下&#xff0c;给予计算机学习能力的领域。 Tom Mitchell&#xff08;1998&#xff09;&#xff1a; 他定义的机器学习是&#xff0c…...

基于STC系列单片机实现定时器扫描数码管显示定时器/计数器产生频率的功能

#define uchar unsigned char//自定义无符号字符型为uchar #define uint unsigned int//自定义无符号整数型为uint #define NixieTubeSegmentCode P0//自定义数码管段码为单片机P0组引脚 #define NixieTubeBitCode P2//自定义数码管位码为单片机P2组引脚 sbit LED P1^0;//位定义…...

Linux环境开发工具yum、makefile的使用 【Linux】

文章目录 Linux软件包管理器 - yumLinux下安装软件的方式yum查找软件包如何实现本地机器和云服务器之间的文件互传卸载软件Linux编译器 - gcc/g 程序的翻译过程1.预编译&#xff08;预处理&#xff09;2.编译&#xff08;生成汇编&#xff09;3.汇编&#xff08;生成机器可识别…...

第六章(6):Python中的函数—闭包和装饰器

1.闭包 在Python中,闭包是指函数与其相关的自由变量的一个整体。当一个函数返回了一个内部函数时,这个内部函数可以访问其定义所在的外部函数中的变量,即使这个外部函数已经返回了。这种特性就叫做闭包。 代码示意: def funca():x = 250def funcb():print(我仍然可以访问…...

Linux--安装与配置虚拟机及虚拟机服务器坏境配置与连接---超详细教学

一&#xff0c;操作系统介绍 1.1.什么是操作系统 操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;是一种系统软件&#xff0c;它是计算机硬件和应用软件之间的桥梁。它管理计算机的硬件和软件资源&#xff0c;为应用程序提供接口和服务&#xff0c;并协调…...

基于SSM的个性化美食推荐系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

JMeter接口测试实战:从登录闭环到分布式压测

1. 为什么接口测试不能只靠“点点点”——从一个被忽略的500错误说起我第一次在客户现场接手一个电商后台系统时&#xff0c;开发说“所有接口都测过了&#xff0c;Postman跑了一遍&#xff0c;没问题”。上线前夜&#xff0c;支付回调接口突然返回500&#xff0c;日志里只有一…...

嵌入式MCU性能评估:CoreMark移植、测试与深度分析指南

1. 项目概述&#xff1a;为什么我们需要CoreMark&#xff1f;在嵌入式开发领域&#xff0c;尤其是基于ARM Cortex-M这类资源受限的微控制器&#xff08;MCU&#xff09;进行选型或性能优化时&#xff0c;一个最直接也最令人头疼的问题就是&#xff1a;这颗芯片到底有多“快”&a…...

安卓上架权限弹窗

https://ask.dcloud.net.cn/article/41194 直接这个网站看&#xff0c;但是要注意&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;真机运行的时候&#xff0c;改了manifest.json的配置要重新打基座...

家居建材营销新趋势:数字化、体验式与可持续方向-佛山鼎策创局破局增长咨询有限公司

鉴于市场竞争程度愈发激烈&#xff0c;加上消费者需求持续升级&#xff0c;家居建材行业已处于营销方式转型的关键要点之处。以往惯用的广告投放手段以及门店促销方式&#xff0c;已无法切合新一代消费者的决策习惯。面对这种形势&#xff0c;行业营销朝着三个主要方向前行&…...

5分钟快速上手!网易云无损音乐下载完整指南:免费获取高品质音乐

5分钟快速上手&#xff01;网易云无损音乐下载完整指南&#xff1a;免费获取高品质音乐 【免费下载链接】Netease_url 网易云无损解析 项目地址: https://gitcode.com/gh_mirrors/ne/Netease_url 想要免费获取网易云音乐的无损音质歌曲吗&#xff1f;Netease_url项目让你…...

Orbit间隔重复算法深度解析:从理论到实践

Orbit间隔重复算法深度解析&#xff1a;从理论到实践 【免费下载链接】orbit Experimental spaced repetition platform for exploring ideas in memory augmentation and programmable attention 项目地址: https://gitcode.com/gh_mirrors/orbit1/orbit Orbit是一个实…...

C++的内存管理详细解释

一、C/C内存分布栈又叫堆栈&#xff0c;非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的。内存映射段是高效的I/O映射方式&#xff0c;用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存&#xff0c;做进程间通信。堆用于程序运行时动态内存分…...

苏姿丰来华,AMD能否借中国市场突破英伟达生态封锁?

苏姿丰访华与AMD战略布局黄仁勋走后第四天&#xff0c;苏姿丰来到上海。上周&#xff0c;黄仁勋在最后一刻挤进特朗普访华队伍&#xff0c;想把英伟达重新带回中国。但他离开北京后&#xff0c;随行企业家很多拿到大单&#xff0c;H200在中国落地仍无明确说法。紧接着&#xff…...

ElevenLabs四川话API响应延迟突增故障复盘:一次DNS劫持引发的方言语音服务中断(附实时监控SLO看板模板)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs四川话语音服务中断事件全景速览 2024年10月12日凌晨&#xff0c;ElevenLabs面向中国西南地区用户提供的方言语音合成服务&#xff08;四川话模型 eleven_turbo_v2.5-sichuan&#xff09;突发…...

如何在智能电视上打造完美的家庭影院:Jellyfin Android TV客户端完整指南

如何在智能电视上打造完美的家庭影院&#xff1a;Jellyfin Android TV客户端完整指南 【免费下载链接】jellyfin-androidtv Android TV Client for Jellyfin 项目地址: https://gitcode.com/gh_mirrors/je/jellyfin-androidtv 想要将智能电视、NVIDIA Shield或亚马逊Fir…...