深入理解队列(Queue)的实现(纯小白进)

目录:

      • 前言
      • 一、 什么是队列?
        • 1.1、 队列的特性
        • 1.2、 队列的图解
      • 二、 队列的详细实现
        • 2.1、 队列不同的实现方式
        • 2.2、 队列结构体
        • 2.3、 队列的初始化
        • 2.4、 入队列
        • 2.5、 出队列
        • 2.6、 获取对头元素
        • 2.7、 获取队尾元素
        • 2.8、 队列的判空
        • 2.9、 队列有效的元素个数
        • 2.10、 队列的销毁
        • 2.11、 队列的应用场景
      • 三、 全篇总结

前言

前篇我们学习了栈,理解了栈的性质和实现。现在我们进入队列的学习,那么什么是队列?队列有什么样的特性?它的应用场景有哪些? 本文会对队列这种数据结构进行进行抽丝剥茧般的讲解,让你彻底学会它。

一、 什么是队列?

队列是一种常见的数据结构,它按照先进先出(FIFO)的原则进行操作。队列中的元素按照进入的顺序排列,新元素插入到队列的一端,称为队尾,已有元素的删除操作则发生在队列的另一端,称为队头。

1.1、 队列的特性
  1. 先进先出(FIFO):队列中的元素按照进入的顺序排列,最先进入的元素最先被删除。
  2. 只能在队尾插入元素:新元素只能从队尾插入。
  3. 只能在队头删除元素:已有元素只能从队头删除。
  4. 队列长度可变:队列的长度可以根据需要动态变化。
  5. 队列可以为空:队列中没有元素时为空队列。
  6. 队列可以为满:队列中的元素数量达到了队列的最大容量时为满队列。
1.2、 队列的图解

在这里插入图片描述

这个可以简单理解成,就像是我们生活中的食堂打饭排队一样,先来的在前面后来的在后面,前面的打完饭后就走了。这就像是数据结构中的队列。

二、 队列的详细实现

2.1、 队列不同的实现方式
  1. 数组实现:使用数组来存储队列中的元素,通过两个指针分别指向队头和队尾。入队操作时,将新元素插入到队尾,同时移动队尾指针;出队操作时,删除队头元素,同时移动队头指针。这种实现方式简单直观,但在动态扩容时需要进行数据的搬移,效率较低。
  2. 链表实现:使用链表来存储队列中的元素,每个节点包含一个元素和一个指向下一个节点的指针。入队操作时,创建一个新节点并插入到链表的末尾;出队操作时,删除链表的头节点。这种实现方式不需要进行数据的搬移,但需要额外的空间来存储指针。

本文我们的队列使用链表的形式来进行队列的实现。这里更推荐链表实现起来不会那么复杂。

在这里插入图片描述

2.2、 队列结构体
typedef int QDataType;//局部,单个节点的信息
typedef struct QueueNode {struct QueueNode* next;QDataType data;
}QNode;
//整体,整个队列的信息
typedef struct Queue {QNode* head;QNode* tail;int size;
}Queue;

对数据类型进行重命名,这样以后需要更换其他数据类型使用的时候只需要更改这一个地方就可以了。

这里有两个结构体,进行了结构体嵌套。定义一个链表的结点,包含当前结点元素和指向下一个结点的指针。然后定义一个队列结构体,队列中两个结构体体指针分别代表队头和队尾,size是当前队列的有效元素个数。

这样做的目的是,方便了队列的头删(出队列)和尾插(入队列),已经获取队列内的元素个数和队尾、队头的元素。

2.3、 队列的初始化
void QueueInit(Queue* pq)
{assert(pq);pq->fornt = NULL;pq->tail = NULL;pq->size = 0;
}

这里先将所以的指针都置空,size为0,因为是初始化所以队中无元素。

2.4、 入队列

在队列插入数据,要先开辟一个结点的空间,用来存放值和下一个结点的地址。这里要进行两种情况的判断:如果队头为空时,代表此时队列中无元素,那么队头和队尾指针指向同一块空间。当队头不为空时,就将队尾的指针指向新开辟的结点。插入新数据后,size的个数++。

在这里插入图片描述

void QueuePush(Queue* pq, QDataType x) {QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode==NULL) {perror("malloc fail");return;}newnode->data = x;newnode->next = NULL;if (pq->head == NULL) {assert(pq->tail == NULL);pq->head = pq->tail = newnode;}else {pq->tail->next = newnode;pq->tail = newnode;}pq->size++;}
2.5、 出队列

在队头删除数据,此处和入队列一样,要进行两种情况的判断:

(1)、 如果队头和队尾指针同时指向一块空间时,此时队列中只有一个元素,所以释放队头或队尾指针都可,然后将队头和队尾指针置空,方便下一次进行插入数据(入队列)。

(2)、队头和队尾指针不相等时,表名队列有最少一个以上的元素,创建一个临时结点用来存放队头指针下一个元素的地址,然后释放队头指针,再让队头指针指向下一个元素。

出队列后,队列中的有效元素个数就少了一个,所以size也要进行 --。

在这里插入图片描述

void QueuePop(Queue* pq) {assert(pq);assert(pq->head != NULL);if (pq->head->next == NULL) {//表示就一个节点free(pq->head);pq->head = pq->tail = NULL;}else {QNode* next = pq->head->next;free(pq->head);pq->head = next;}pq->size--;}
2.6、 获取对头元素

要获取元素前需要进行判空,如果队列是空,那么就会报错。

队头指针指向的就是队列的首元素地址,进行解引用就可以获取队头的元素。

QDataType QueueFront(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));return  pq->head->data;
}

和QueuePush,QueuePop搭配在一起的测试运行结果如下:
在这里插入图片描述

2.7、 获取队尾元素

要获取元素前需要进行判空,如果队列是空,那么就会报错。

队头指针指向的就是队尾的首元素地址,进行解引用就可以获取队尾的元素。

QDataType QueueBack(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));return  pq->tail->data;
}
2.8、 队列的判空

队列如果为空的情况下代表队头指针是空,此时队列无元素。

bool QueueEmpty(Queue* pq) {assert(pq);return pq->size == 0;
}
2.9、 队列有效的元素个数

我们先前定义的size就是队列中有效元素的个数。

int  QueueSize(Queue* pq) {assert(pq);return pq->size;
}
2.10、 队列的销毁

因为队列是链表实现的,所以这里的释放空间要写成循环,释放队列中每一个结点的空间。

创建临时指针,让cur去迭代。最后队头和队尾指针都置空,size归0。

void QueueDestroy(Queue* pq) {assert(pq);QNode* cur = pq->head;while (cur) {QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;pq->size = 0;
}
2.11、 队列的应用场景

队列在计算机科学和软件开发中有广泛的应用场景:

  1. 任务调度:队列可以用来实现任务调度系统,将待执行的任务按照先后顺序排列,每次从队头取出一个任务进行执行,保证任务按照顺序执行。
  2. 消息传递:队列可以用来实现消息传递系统,消息发送方将消息入队,消息接收方从队头出队获取消息。这种方式可以实现异步消息传递,并且可以处理消息的积压情况。
  3. 缓冲区:队列可以用来实现缓冲区,例如网络数据传输中的数据包缓冲区、磁盘读写中的数据缓冲区等。数据可以按照顺序入队,然后按照顺序出队进行处理,保证数据的有序性和流畅性。
  4. 广度优先搜索:在图的广度优先搜索算法中,使用队列来存储待访问的节点,每次从队头取出一个节点进行访问,并将其邻接节点入队。这样可以保证按照层次遍历图的节点,从而实现广度优先搜索。
  5. 线程池:在多线程编程中,线程池可以使用队列来实现任务的调度。将待执行的任务入队,线程池中的线程从队头取出任务进行执行,保证任务的有序执行和线程的复用。

以上只是一些常见的应用场景,队列还可以用于解决其他问题,如数据流量控制、请求排队、打印队列等。队列的先进先出特性使其在这些场景下能够提供高效的数据处理和调度能力。

三、 全篇总结

本篇对队列这种数据结构进行了概念的说明,对队列的实现细致入微,最后普及了队列这种数据结构的泛用性!希望大家搭配和栈的学习一起食用。
需要源代码自取

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

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

相关文章

Kind部署的K8s证书过期后的解决方案

证书通常有效期为1年,一年后服务将不可用解决方案就是更新证书 1. 找到 Kind 集群的控制平面容器名称,容器名称不一定是这个 docker ps --filter "namekind-control-plane"2. 进入 Kind 控制平面的容器: docker exec -it kind-control-plane…

洛谷入门刷题Day5(想刷水题结果被水题刷了)

P1304 哥德巴赫猜想 题目描述 输入一个偶数 N N N,验证 4 ∼ N 4\sim N 4∼N 所有偶数是否符合哥德巴赫猜想:任一大于 2 2 2 的偶数都可写成两个质数之和。如果一个数不止一种分法,则输出第一个加数相比其他分法最小的方案。例如 10 10…

论文笔记:Ontology-enhanced Prompt-tuning for Few-shot Learning

论文来源:WWW 2022 论文地址:https://arxiv.org/pdf/2201.11332.pdfhttps://arxiv.org/pdf/2201.11332.pdf 论文代码:暂未公开 笔记仅供参考,撰写不易,请勿恶意转载抄袭! Abstract 小样本学习旨在基于…

Linux——传输层协议

目录 一再谈端口号 1端口号范围划分 2两个问题 3理解进程与端口号的关系 二UDP协议 1格式 2特点 3进一步理解 3.1关于UDP报头 3.2关于报文 4基于UDP的应用层协议 三TCP协议 1格式 2TCP基本通信 2.1关于可靠性 2.2TCP通信模式 3超时重传 4连接管理 4.1建立…

数据挖掘学习笔记:朴素贝叶斯 | Python复现

数据挖掘学习笔记:朴素贝叶斯 机器学习系列(四):朴素贝叶斯(华强买瓜版) - yyxy的文章 - 知乎 十分钟,让你再也忘不掉贝叶斯分类 - VoidHaruhi的文章 - 知乎 《机器学习》(西瓜书&am…

基于Arduino的简易收音机

DIY FM收音机:使用Arduino和Si4703模块打造 引言 在本项目中,我们将使用Arduino Nano和Si4703 FM调谐模块来构建一个功能完备的FM收音机接收器。这个易于跟随的指南非常适合想要深入无线电频率和无线通信世界的业余爱好者和电子爱好者。 Si4703模块是…

说下SSL/TLS四次握手过程?

参考自:SSL/TLS四次握手过程是怎么样的?HTTPS、SSL、TLS三者之间的联系和区别 一.SSL/TLS 简介 SSL(Secure Socket Layer 安全套接层)是基于 HTTPS 下的一个协议加密层,用于解决 HTTP 在传输数据时使用明文而导致的不安全问题。 SSL 是 HT…

cuda编程模型

host和device: host:即CPU,CPU所关联的内存就叫host memorydevice:即GPU,GPU内的内存就叫device memory运行CUDA程序主要有三步:1)host-to-device transfer:将数据从host memory拷到…

Qt(简介)

1. Qt简介 Qt是一个基于C的图形用户界面(GUI)框架,可以开发可视化人机交互程序,但是这并不是Qt的全部。Qt除了可以绘制漂亮的界面外,还包含很多其他的功能:多线程、数据库、图像处理、音视频处理、网络通信…

Python画笔案例-085 绘制 3D效果文字

1、绘制3D效果文字 通过 python 的turtle 库绘制 3D效果文字,如下图: 2、实现代码 绘制 3D效果文字,以下为实现代码: """3D效果文字.py """ import turtle# 给Turtle类增加addx和addy方法 turtle.Turtle.addx = lambda self,dx

OpenUAV:首个专为现实无人机视觉语言导航设计的大规模轨迹数据集,由大约 12k 个轨迹组成,涵盖了多种环境和复杂的飞行动态。

2024-10-10,由北京航空航天大学人工智能研究所、香港中文大学MMLab以及感知与交互智能中心共同创建了OpenUAV数据集,首个专为现实无人机(UAV)视觉语言导航(VLN)任务设计的大型轨迹数据集,该数据…

2023年云南省职业院校技能大赛(网络建设与运维赛项)

2023年云南省职业院校技能大赛 “网络搭建与应用”赛项样题 2023年8月 竞赛说明 一、竞赛内容分布 “网络搭建与应用”竞赛共分三个部分,其中: 第一部分:网络理论测试(100分) 第二部分:网络建设与调试&…

精准管理知识资产:十大内部知识库工具全解析

在当今竞争激烈的市场环境中,知识资产已成为企业核心竞争力的重要组成部分。为了更好地管理和利用这些宝贵的知识资源,选择合适的内部知识库工具至关重要。本文将为您介绍十款高效、实用的内部知识库工具,帮助您实现知识资产的精准管理。 1.…

SldWorks问题 2. 矩阵相关接口使用上的失误

问题 在计算三维点在图纸(DrawingDoc)中的位置时,就是算不对,明明就4、5行代码,怎么看都是很“哇塞”的,毫无问题的。 但结果就是不对。 那就调试一下吧,调试后发现生成的矩阵很不对劲&#…

架构设计笔记-15-面向服务架构设计理论与实践

目录 知识要点 案例分析 1.微服务架构 2.微服务 3.微服务架构 4.SOA与微服务 5.基于微服务架构的系统/传统单体式系统 论文 1.论微服务架构及其应用 知识要点 服务组件体系结构(Service Component Architecture,SCA)是面向服务体系…

重头开始嵌入式第四十九天(Linux内核驱动 内核编译 向内核添加新文件)

目录 内核编译: 什么是uImage? 一、产生背景 二、主要特点 三、使用方式 uImage与zImage与Image的区别? 向内核添加新驱动文件: 内核编译: 什么是uImage? uImage 是一种用于嵌入式系统的 Linux 内核…

windows安装deepspeed setup.py 207行找不到文件

一直报莫名奇妙的错误,查了半天也没查到 去看了一下源码,需要安装git,我没有安装 git命令获得信息也没啥用 直接注释掉 成功运行

高效管理知识资产:十大内部知识库软件一览

在当今竞争激烈的市场环境中,知识资产已成为企业核心竞争力的重要组成部分。为了更好地管理和利用这些宝贵的知识资源,选择合适的内部知识库工具至关重要。本文将为您介绍十款高效、实用的内部知识库工具,帮助您实现知识资产的精准管理。 1.…

【argparse】 菜鸟实用教程指南

文章目录 0. 引言1. argparse简介2. argparse的使用3. 实例操作4. 代码运行4.1 命令行执行4.1 IDE执行 5. 总结 0. 引言 在深度学习的过程中,我们常常需要操作和调参大量的参数。如果采用硬编码(直接在代码中赋值)的方式来设置这些参数&…

补充面试知识点

jwt鉴权 实现登录流程 jwt鉴权登录实现步骤(JWT工具类拦截器前端配置)——前后端鉴权方案和使用_jwtsigner-CSDN博客 就是前端每一次刷新页面的时候 都判断一下发来的请求头里边的token信息 通过token识别用户信息和登录状态也就是id 线程池的执行流程 …