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

数据结构入门:队列

目录

文章目录

前言

1.队列

1.1 队列的概念及结构

 1.2 队列的实现

 1.2.1 队列的定义

1.2.2队列的初始化

 1.2.3 入队

 1.2.4 判空

 1.2.5 出队

 1.2.6 队头队尾数据

1.2.7 队列长度

1.2.8 队列销毁

总结


前言

        队列,作为一种重要的数据结构,在计算机科学中扮演着重要的角色,它按照先进先出(FIFO)的原则进行操作。它可以用来解决许多实际问题,队列的应用范围广泛,从操作系统中的进程调度,到网络中的数据传输,再到算法中的搜索和排序,队列无处不在。那么接下来,让我们一同开始这段关于队列的探索之旅吧!


1.队列

1.1 队列的概念及结构

 队列:

        只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特性。

  • 入队列:进行插入操作的一端称为队尾
  • 出队列:进行删除操作的一端称为队头

 1.2 队列的实现

        队列的特性是先进先出,这里就要考虑选择顺序表还是链表来实现队列。队列需要大量的头删尾插的操作,顺序表进行头删的效率太低,所以这里我们选用链式结构来实现。

 1.2.1 队列的定义

 

typedef int Datatype;
typedef struct QueueNode
{struct QueueNode* next;Datatype data;}QueueNode;

         和定义链表的节点一样。但是也有所不同,我们知道队列需要大量的头删和尾插,为了方便尾插和头删我们最好再创建两个指针,一个指向头,另一个指向尾。那这样岂不是需要二级指针解决吗?

        这里我将会介绍一种新的方法来解决头删问题,前边我们已经知道对链表头进行操作方法有三种:

  • 一种是使用二级指针来达到修改头节点的目的
  • 另外一种是使用函数返回类型来达到修改的目的
  • 此外我们还可以使用带头结点的链表来解决对链表头操作时需要特殊处理的情况

         进行尾插操作时,需要传递头指针和尾指针,这样使用时函数的参数变多了,调用函数时也比较费劲,那这里我们不如直接再定义一个结构体来存放队列的头指针和尾指针,以及队列的长度。

typedef int Datatype;
typedef struct QueueNode
{struct QueueNode* next;Datatype data;}QueueNode;
typedef struct Queue
{QueueNode* head;QueueNode* tail;int size;
}Que;

        这样我们传参时就只需传第二个结构体就可以进行了。通过第二个结构体找到第一个结构体,然后进行一系列头删、尾插的操作,使用时实质和二级指针类似,它效果和带头节点的链表类似,只需要一级指针就可以解决。

        虽然栈和队列的逻辑非常简单,但是它们的结构却变得更加复杂了,链表和顺序表是后续数据结构学习的基础,一定要灵活掌握。

1.2.2队列的初始化

void QueueInit(Que* pq)
{assert(pq);pq->head = pq->tail = NULL;pq->size = 0;
}

        初始化就非常简单了,只需要将头指针和尾指针进行初始化置为NULL,长度置为0。这里我们也不需要创建新节点,由于我们就只要一个接口需要创建新节点(尾插),所以不需要封装成函数,对节点进行初始化。

我们在调用函数时也非常简单,将第二个结构体传过去:

Que q;//创建结构体变量QueueInit(&q);

 1.2.3 入队

void QueuePush(Que* pq, Datatype x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("malloc");exit(-1);}newnode->data = x;newnode->next = NULL;if (pq->tail == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}pq->size++;
}

         在入队操作时,我们需要创建新的节点,这里注意:创建新节点是为队列的节点申请空间,定义的第一个结构体才是队列节点的类型,所以新建节点是的类型也应该与第一个结构体对于,链表没有节点时,这时需要将头指针和尾指针指向新节点,进行特殊处理。后续再次入队就可以直接将新节点链接到尾节点的后边。入队新节点的同时注意将size++;记录队列长度。

 1.2.4 判空

入队之后就是出队,但考虑到后续多个接口中需要判空,这里就提前封装成一个函数

 

bool IsEmpty(Que* pq)
{assert(pq);return (pq->head == NULL);
}

 函数类型为bool类型,该类型返回值只有true(1)和false(0)两种,所以最后直接返回条件:pq->head == NULL如果为真就为true,假就为false。

 1.2.5 出队

void QueuePop(Que* pq)
{assert(pq);assert(!IsEmpty(pq));if (pq->head->next == NULL){free(pq->head);pq->head = pq->tail = NULL;}else{QueueNode* next = pq->head->next;free(pq->head);pq->head = next;}pq->size--;
}

         出队需要先判断队列是否为NULL,然后将头指针向后移动(改变结构体指针),释放掉第一个节点,然后队列长度size--,但需要考虑一下特殊情况,就是删空的情况,如果只剩下一个节点就可以直接释放掉,然后将头指针和尾指针置为NULL。

 1.2.6 队头队尾数据

//队头
Datatype QueueFront(Que* pq)
{assert(pq);assert(!IsEmpty(pq));return pq->head->data;
}
//队尾
Datatype QueueBlack(Que* pq)
{assert(pq);assert(!IsEmpty(pq));return pq->tail->data;
}

         这里没什么好说的,直接返回队列头指针和尾指针指向节点的数据。但注意都需要进行判空操作。

1.2.7 队列长度

int QueueSize(Que* pq)
{assert(pq);return pq->size;
}

         直接返回队列的size即可。

1.2.8 队列销毁

 

void DestoryQueue(Que* pq)
{assert(pq);QueueNode* cur = pq->head;while (cur){QueueNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;pq->size = 0;
}

         像链表一样,遍历队列一个一个的销毁节点,最后将指针置为NULL,队列长度size置为0。

        在链表学习以来部分同学会不会有这样的疑惑:销毁空间是不是不允许部分销毁吗?那一个一个节点的销毁不就可以部分销毁?那是因为标准C规定的是,释放空间时,一个malloc申请的空间必须全部释放,不可以将一个malloc申请的空间部分释放,而链表是每次增加节点就申请一次空间(malloc一次),每个节点都是相对独立的空间,所以需要一个个的遍历逐个销毁。


总结

        希望通过这篇博客,可以使你对队列有了更深入的了解,并能够应用这一概念解决实际问题。无论是在计算机科学中还是在日常生活中,队列都是一种重要的工具和思维方式,它能够帮助我们更好地组织和管理事务。最后,感谢阅读!      

相关文章:

数据结构入门:队列

目录 文章目录 前言 1.队列 1.1 队列的概念及结构 1.2 队列的实现 1.2.1 队列的定义 1.2.2队列的初始化 1.2.3 入队 1.2.4 判空 1.2.5 出队 1.2.6 队头队尾数据 1.2.7 队列长度 1.2.8 队列销毁 总结 前言 队列,作为一种重要的数据结构,在计算机科学中扮演…...

面试热题(合并K个升序链表)

给定一个链表数组,每个链表都已经按升序排列。 请将所有链表合并到一个升序链表中,返回合并后的链表。 输入:lists [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [1->4->5,1…...

优化过多if else判断代码

有些判断难免会遇到很多 if else 看起来很头疼 下面是一个优化示例 修改前 if(this.$route.query.deptId){this.queryParams.deptId this.$route.query.deptId}else if (this.$store.state.adaptation.roleSign.includes(fengongsicengji)) {const ancestorsId this.$stor…...

最强自动化测试框架Playwright (27)-跟踪查看器

Playwright Trace Viewer 是一个 GUI 工具,可帮助您在脚本运行后探索记录的 Playwright 跟踪。可以本地打开,也可以在trace.playwright.dev.打开, 录制跟踪文件 使用context.tracing.start进行录制,使用stop方法保存录制文件 b…...

【工作中问题解决实践 十一】Kafka消费者消费堆积且频繁rebalance

最近有点不走运,老是遇到基础服务的问题,还是记着点儿解决方法,以后再遇到快速解决吧,今天遇到这个问题倒不算紧急,但也能通过这个问题熟悉一下Kafka的配置。 问题背景 正在开会的时候突然收到一连串的报警&#xff…...

ChatGpt提示词大全

中文版本 行为 提示词 Linux终端 我希望你能充当一个linux终端。我将输入命令,你会回复终端应该显示什么。我想让你只回复在一个唯一的代码块内的终端输出,而没有别的。不要写一些解释。不要键入命令,除非我指示你这样做。当我需要用英语告…...

利用SimpleDateFormat或者LocalDateTime生成格式为“yyyy-MM-dd HH:mm:ss“的当前时间

java程序: // 利用LocalDateTime生成格式为"yyyy-MM-dd HH:mm:ss"的当前时间 DateTimeFormatter formatter DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime now LocalDateTime.now(); String time1 now.format(format…...

使用 Postman 批量发送请求的最佳实践

目录 背景 批量发送? 起因 思考 Postman 批量发送接口 创建集合和接口 批量发送接口 资料获取方法 背景 最近写了几个接口: 获取 books 的接口获取 likes 的接口获取 collections 的接口 但是我还是不放心,因为这些接口到底稳不稳…...

Docker一键部署项目,无需登录XShell

文章目录 一键部署项目Docker手动部署SpringBoot项目编写docker部署的脚本文件script.sh 脚本内容 特别注意!编写dockerfiledockerfile 文件内容 上传后端服务的jar包到服务器中执行 script 脚本部署后端服务 自动部署SpringBoot项目引入jsch依赖编写jsch工具类执行…...

GIt Squash 多个提交压缩提交

假设你有一个名为 feature 的分支,它包含三个提交(A, B, C),并且你想将这三个提交压缩成一个。下面是如何做到这一点的。 首先,找出你要开始压缩的那个最早提交的哈希值。在这个例子中,我们假设 A 是最早的…...

【数据结构】栈与队列

1 栈 1.1 栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出 LIFO (Last In First Out) 的原则。 压栈:栈…...

突然让做性能测试?试试RunnerGo

当前,性能测试已经是一名软件测试工程师必须要了解,甚至熟练使用的一项技能了,在工作时可能每次发版都要跑一遍性能,跑一遍自动化。性能测试入门容易,深入则需要太多的知识量,今天这篇文章给大家带来&#…...

(7)(7.4) 集结航点

文章目录 7.4.1 概述 7.4.2 设置集结航点 7.4.3 飞行示例 7.4.4 附录 7.4.1 概述 通常情况下,当固定翼或旋翼飞机进入"返回发射"(Return to Launch (RTL))模式(通常由自动驾驶仪失控保护触发)(failsafe)时,默认行为…...

基于kubeadm部署K8S集群:上篇

目录 一、环境准备 1、主机初始化配置 2、配置主机名绑定hosts,不同主机名称不同 3、主机配置初始化 4、部署docker环境 二、部署kubernetes集群 1、组件介绍 2、所有主机配置阿里云yum源 3、安装kubelet 、kubeadm 、kubectl 4、配置init-config.yaml 5、…...

机器学习-特征选择:如何使用递归特征消除算法自动筛选出最优特征?

一、引言 在实际应用中,特征选择作为机器学习和数据挖掘领域的重要环节,对于提高模型性能和减少计算开销具有关键影响。特征选择是从原始特征集中选择最相关和最具区分力的特征子集,以提高模型的泛化能力和可解释性。 特征选择在实践中具有以…...

学生成绩管理系统V1.0

某班有最多不超过30人(具体人数由键盘输入)参加某门课程的考试,用一维数组作函数参数编程实现如下学生成绩管理: (1)录入每个学生的学号和考试成绩; (2)计算课程的总分…...

嵌入式:ARM Day1

1. 思维导图 2.作业一 3.作业2...

Android 网络协议与网络编程

一、TCP/IP协议 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联 协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP 协议组成。协议采用了4层的层级结构。…...

【讯飞星火认知大模型】大模型之星火手机助理

目录 1. 讯飞星火认知大模型介绍 2. API 申请 3. 星火手机助理 4. 效果展示 1. 讯飞星火认知大模型介绍 讯飞星火认知大模型是科大讯飞自研的基于深度学习的自然语言处理模型,它可以理解和生成中文,执行多种任务,如问答、翻译、写作、编…...

centos中的swap.img可以删除吗

swap.img 是 CentOS 系统中的交换分区文件,用于辅助内存管理。交换分区在系统内存不足时用于存储不常用的数据,而不是直接写入硬盘。一般情况下,不建议删除交换分区文件,因为它对系统的正常运行非常重要。 如果您真的希望删除交换…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...