数据结构从入门到精通——队列

队列

  • 前言
  • 一、队列
    • 1.1队列的概念及结构
    • 1.2队列的实现
    • 1.3队列的实现
    • 1.4扩展
  • 二、队列面试题
  • 三、队列的具体实现代码
    • Queue.h
    • Queue.c
    • test.c
    • 队列的初始化
    • 队列的销毁
    • 入队列
    • 出队列
    • 返回队头元素
    • 返回队尾元素
    • 检测队列是否为空
    • 检测元素个数


前言

队列是一种特殊的线性数据结构,遵循先入先出(FIFO)的原则。它只允许在队列的末尾添加元素(称为入队操作),并从队列的开头移除元素(称为出队操作)。队列在多种应用中发挥着重要作用,如计算机系统的任务调度、打印机作业管理以及多线程编程中的线程同步等。


一、队列

1.1队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头
在这里插入图片描述

1.2队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在这里插入图片描述

1.3队列的实现

// 链式结构:表示队列 
typedef struct QListNode 
{ struct QListNode* _pNext; QDataType _data; 
}QNode; // 队列的结构 
typedef struct Queue 
{ QNode* _front; QNode* _rear; 
}Queue; // 初始化队列 
void QueueInit(Queue* q); 
// 队尾入队列 
void QueuePush(Queue* q, QDataType data); 
// 队头出队列 
void QueuePop(Queue* q); 
// 获取队列头部元素 
QDataType QueueFront(Queue* q); 
// 获取队列队尾元素 
QDataType QueueBack(Queue* q); 
// 获取队列中有效元素个数 
int QueueSize(Queue* q); 
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q); 
// 销毁队列 
void QueueDestroy(Queue* q);

1.4扩展

另外扩展了解一下,实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型
时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。

在这里插入图片描述
在这里插入图片描述

二、队列面试题

  1. 用队列实现栈

  2. 用栈实现队列

  3. 设计循环队列

  4. 循环队列的存储空间为 Q(1:100) ,初始状态为 front=rear=100 。经过一系列正常的入队与退队操作后,front=rear=99 ,则循环队列中的元素个数为( )
    A 、1
    B 、2
    C 、99
    D、 0或者100

  5. 以下( )不是队列的基本运算?
    A 、从队尾插入一个新元素
    B、 从队列中删除第i个元素
    C、 判断一个队列是否为空
    D、 读取队头元素的值

  6. 现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为?(假设
    队头不存放数据)
    A 、(rear - front + N) % N + 1
    B 、(rear - front + N) % N
    C 、(rear - front) % (N + 1)
    D 、(rear - front + N) % (N - 1)

答案:DBB

三、队列的具体实现代码

Queue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int QDatatype;
typedef struct QueueNode
{QDatatype val;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;
//队列的初始化
void QueueInit(Queue* pq);
//队列的销毁
void QueueDestroy(Queue* pq);//入队列
void QueuePush(Queue* pq, QDatatype x);
//出队列
void QueuePop(Queue* pq);//队头元素
QDatatype QueueFront(Queue* pq);
//队尾元素
QDatatype QueueBack(Queue* pq);//检测是否为空
bool QueueEmpty(Queue* pq);//检测元素个数
int QueueSize(Queue* pq);

Queue.c

#include "Queue.h"
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
void QueuePush(Queue* pq, QDatatype x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("newnode malloc :");return;}newnode->val = x;newnode->next = NULL;if (pq->ptail){pq->ptail->next = newnode;pq->ptail = newnode;}else{pq->phead = pq->ptail = newnode;}pq->size++;
}
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
void QueuePop(Queue* pq)
{assert(pq);//assert(!QueueEmpty(pq));assert(pq->phead != NULL);if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}
QDatatype QueueFront(Queue* pq)
{assert(pq);assert(pq->phead != NULL);return pq->phead->val;
}
QDatatype QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail != NULL);return pq->ptail->val;
}
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}

test.c

#include"Queue.h"int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);printf("%d ", QueueFront(&q));QueuePop(&q);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));QueuePop(&q);}QueueDestroy(&q);return 0;
}

队列的初始化

//队列的初始化
void QueueInit(Queue* pq);
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}

队列的初始化是数据结构学习中不可或缺的一步,它标志着队列这一特定数据存储形式的诞生。队列,又称先进先出(FIFO)的数据结构,允许我们在一端(通常是队尾)添加元素,而在另一端(通常是队头)移除元素。这种特性使得队列在多种应用场景中发挥着重要作用,如操作系统中的任务调度、网络中的缓冲管理等。

在初始化队列时,我们首先需要分配一定的存储空间来存放队列元素。这个存储空间可以是数组、链表或其他适合的数据结构。初始化过程中,我们还需设置两个指针,分别指向队头和队尾,以便进行元素的添加和移除操作。

完成初始化后,队列就处于空状态,即没有元素可供处理。此时,任何尝试从队列中移除元素的操作都会失败,因为队列是空的。然而,可以向队列中添加元素,这些元素将按照添加的顺序依次排列。

随着元素的不断加入,队尾指针会向后移动,指向队列中最后一个元素。当需要从队列中移除元素时,队头指针会向前移动,指向下一个待处理的元素。这种指针的移动保证了队列的先进先出特性,即最早加入队列的元素将最先被移除。

除了基本的添加和移除操作外,队列还支持其他一些有用的操作,如检查队列是否为空、判断队列是否已满等。这些操作使得队列在实际应用中更加灵活和高效。

总之,队列的初始化是队列生命周期的开始,它为队列的后续操作提供了基础。通过对队列的合理初始化和管理,我们可以有效地处理各种需要先进先出处理顺序的场景,提高程序的效率和稳定性。

队列的销毁

//队列的销毁
void QueueDestroy(Queue* pq);
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}

队列的销毁涉及清除所有队列元素并释放队列占用的内存空间,确保资源得到正确回收。这通常涉及遍历队列,逐个删除元素,并解除队列与其他数据结构或资源的关联。销毁队列后,其不再可用,需重新创建才能使用。

入队列

//入队列
void QueuePush(Queue* pq, QDatatype x);
void QueuePush(Queue* pq, QDatatype x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("newnode malloc :");return;}newnode->val = x;newnode->next = NULL;if (pq->ptail){pq->ptail->next = newnode;pq->ptail = newnode;}else{pq->phead = pq->ptail = newnode;}pq->size++;
}

入队列(Enqueue)是队列操作的一种,指的是将一个元素添加到队列的尾部。在队列这种先进先出(FIFO)的数据结构中,新添加的元素将排在所有已有元素的后面,等待被处理或移除。入队列操作不会改变队列中已有元素的顺序,保证了队列的先进先出特性。在实际应用中,入队列常用于实现缓冲、任务调度、消息传递等场景。

出队列

//出队列
void QueuePop(Queue* pq);
void QueuePop(Queue* pq)
{assert(pq);//assert(!QueueEmpty(pq));assert(pq->phead != NULL);if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}

出队列是指从队列中移除并返回队列头部的元素,通常用于实现先进先出(FIFO)的数据结构。在出队列操作中,队列头部元素被移除并返回,队列中的其他元素则向前移动一位。出队列操作的时间复杂度通常为O(1),因为它只涉及到对队列头部元素的移除和返回,不需要遍历整个队列。在实际应用中,出队列操作常用于缓存管理、任务调度、网络流量控制等场景。

返回队头元素

//队头元素
QDatatype QueueFront(Queue* pq);
QDatatype QueueFront(Queue* pq)
{assert(pq);assert(pq->phead != NULL);return pq->phead->val;
}

队列是一种特殊的线性表,只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。队列具有先进先出(FIFO)的特性。

"返回队头元素"是对队列进行的一种操作,即获取队列前端(队头)的元素,但并不从队列中删除该元素。这通常用于查看队列中的第一个元素,但不改变队列的状态。

返回队尾元素

//队尾元素
QDatatype QueueBack(Queue* pq);
QDatatype QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail != NULL);return pq->ptail->val;
}

检测队列是否为空

//检测是否为空
bool QueueEmpty(Queue* pq);
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}

检测队列是否为空,可以通过检查队列的头部和尾部指针或索引来实现。如果头部和尾部指针或索引相同,说明队列为空;否则,队列不为空。此外,也可以使用队列提供的相关函数或方法,如isEmpty()等,来检测队列是否为空。在实际应用中,检测队列是否为空是常见的操作,常用于控制程序的流程。

在C语言中,没有相关的库函数检验是否为空,在c++中会有相关的数据结构的库

检测元素个数

//检测元素个数
int QueueSize(Queue* pq);
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}

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

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

相关文章

Python 初步了解urllib库:网络请求的利器

目录 urllib库简介 request模块 parse模块 error模块 response模块 读取响应内容 获取响应状态码 获取响应头部信息 处理重定向 关闭响应 总结 在Python的众多库中&#xff0c;urllib库是一个专门用于处理网络请求的强大工具。urllib库提供了多种方法来打开和读取UR…

STM32 HAL库RTC复位丢失年月日的解决办法

STM32 HAL库RTC复位丢失年月日的解决办法 0.前言一、实现方式1.CubeMX配置&#xff1a;2.MX_RTC_Init()函数修改2.编写手动解析函数 二、总结 参考文章&#xff1a;stm32f1 cubeMX RTC 掉电后日期丢失的问题 0.前言 最近在使用STM32F103做RTC实验时&#xff0c;发现RTC复位后时…

基于Java的物管系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术介绍 3 1.1 JSP介绍 3 1.2 MySQL介绍 3 1.3 B/S开发模式 3 1.4 Java介绍 4 2 系统分析 5 2.1 可行性研究 5 2.1.1技术可行性 5 2.2.2经济可行性 5 2.3.1操作可行性 5 2.2 需求分析 6 2.2.1系统用例图 6 2.2.2系统功能模块需求分析…

机器学习--循环神经网络(RNN)1

一、简介 循环神经网络&#xff08;Recurrent Neural Network&#xff09;是深度学习领域中一种非常经典的网络结构&#xff0c;在现实生活中有着广泛的应用。以槽填充&#xff08;slot filling&#xff09;为例&#xff0c;如下图所示&#xff0c;假设订票系统听到用户说&…

揭秘接口测试:完整流程指南!

在讲接口测试之前&#xff0c;首先需要给大家申明下&#xff1a;接口测试对于测试人员而言&#xff0c;非常非常重要&#xff0c;懂功能测试接口测试&#xff0c;就能在企业中拿到一份非常不错的薪资。 这么重要的接口测试&#xff0c;一般也是面试笔试必问。为方便大家更好的…

【C/C++】常量指针与指针常量的深入解析与区分(什么是const int * 与 int * const ?)

目录 一、前言 二、const 的简单介绍 三、常量指针 &#x1f50d;介绍与分析 &#x1f4f0;小结与记忆口诀 四、指针常量 &#x1f50d;介绍与分析 &#x1f4f0;小结与记忆口诀 五、总结与提炼 六、共勉 一、前言 在【C/C】的编程中&#xff0c;指针与const关键字的组合…

防御保护IPSEC实验

要求&#xff1a;在FW5和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24. 因为是双机热备状态则只需要配置FW1主设备。 新建ACL待加密数据流 安全建议&#xff1a; IPSec参数配置 FW3配置如下与FW1类似&#xff1a; FW1中新建安全策略…

链表|19.删除链表的倒数第N个节点

力扣题目链接 struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {//定义虚拟头节点dummy 并初始化使其指向headstruct ListNode* dummy malloc(sizeof(struct ListNode));dummy->val 0;dummy->next head;//定义 fast slow 双指针struct ListNode* f…

论文汇总:Rectifying the Shortcut Learning of Background for Few-Shot Learning

原文解读&#xff1a; 论文解读&#xff1a;Rectifying the Shortcut Learning of Background for Few-Shot Learning-CSDN博客 文章汇总 问题&动机&解决方法 图像背景是一种有害知识的来源&#xff0c;这是少数镜头学习模型容易吸收的(问题) 通过在训练和评估中提…

TI IWR6843ISK ROS驱动程序搭建

1、设备准备 1.1 硬件设备 1&#xff09;TI IWR 6843 ISK 1块 2&#xff09;Micro USB 数据线 1条 1.2 系统环境 1&#xff09;VMware Workstation 15 Player 虚拟机 2&#xff09;Ubuntu18.04 并安装有 ROS1 系统 如若没有安装 ROS 系统&#xff0c;可通过如下指令进行…

【分库分表】基于mysql+shardingSphere的分库分表技术

目录 1.什么是分库分表 2.分片方法 3.测试数据 4.shardingSphere 4.1.介绍 4.2.sharding jdbc 4.3.sharding proxy 4.4.两者之间的对比 5.留个尾巴 1.什么是分库分表 分库分表是一种场景解决方案&#xff0c;它的出现是为了解决一些场景问题的&#xff0c;哪些场景喃…

Solidity攻击合约:“被偷走的资金”

在以太坊智能合约开发中&#xff0c;Solidity是最常用的编程语言。然而&#xff0c;由于代码编写不当或缺乏安全意识&#xff0c;合约可能面临各种攻击。本文将通过一个简单的Solidity合约示例&#xff0c;展示一个潜在的攻击合约&#xff0c;并分析其相对于原本合约的危害以及…

计算机设计大赛 疲劳驾驶检测系统 python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#x…

024—pandas 将一列数据等份变形

前言 今天我们将一个 Series 序列数据转为 DataFrame结构。我们将用么 pd.cut() 对数据进行分箱&#xff0c;也会用到 NumPy 的 np.reshape() 对阵列数据进行变形。接下来我们看看具体的需求&#xff0c;再分析一下解决思路&#xff0c;最后用代码实现它。 需求&#xff1a; …

flink实战--Flink任务资源自动化优化

背景 在生产环境Flink任务资源是用户在实时平台端进行配置,用户本身对于实时任务具体配置多少资源经验较少,所以存在用户资源配置较多,但实际使用不到的情形。比如一个 Flink 任务实际上 4 个并发能够满足业务处理需求,结果用户配置了 16 个并发,这种情况会导致实时计算资…

《Effective Modern C++》- 极精简版 15-21条

本文章属于专栏《业界Cpp进阶建议整理》 继续上篇《Effective Modern C》- 极精简版 5-14条。本文列出《Effective Modern C》的15-21条的个人理解的极精简版本。 Item15、尽量使用constexpr constexpr形容对象 constexpr对象都是const&#xff0c;但是const对象不一定是conste…

七、门控循环单元语言模型(GRU)

门控循环单元&#xff08;Gated Recurrent Unit&#xff0c;GRU&#xff09;是 LSTM 的一个稍微简化的变体&#xff0c;通常能够提供同等的效果&#xff0c;并且计算训练的速度更快。 门控循环单元原理图&#xff1a;参考门控循环单元 原理图中各个图形含义&#xff1a; X(t)&a…

C语言逗号运算符(,)

在C语言中&#xff0c;逗号运算符&#xff08;,&#xff09;用于在表达式中分隔多个子表达式&#xff0c;并按照从左到右的顺序依次计算这些子表达式。逗号运算符的运算结果是最后一个子表达式的值。 逗号运算符的底层行为是依次计算每个子表达式&#xff0c;并将每个子表达式…

gumbel-softmax如何实现离散分布可微+torch代码+原理+证明

文章目录 背景方法通俗理解什么是重参数化gumbel-softmax为什么是gumbeltorch实现思考 背景 这里举一个简单的情况&#xff0c;当前我们有p1, p2, p3三个概率&#xff0c;我们需要得到最优的一个即max(p1, p2, p3)&#xff0c;例如当前p3 max(p1, p2, p3)&#xff0c;那么理想…

【从部署服务器到安装autodock vina】

注意&#xff1a;服务器 linux系统选用ubuntu 登录系统&#xff0c;如果没有图形化见面可以先安装图形化界面 可以参考该视频 --> linux安装图形化界面 非阿里云ubuntu 依次执行以下命令 sudo apt-get update sudo apt-get install gnome sudo reboot阿里云ubuntu 需多执…