【数据结构】—— 队列

    • 1、队列的概念
    • 2、队列的结构
      • 如何选择合适的数据结构实现队列(数组or链表)
    • 3、队列的链式存储
      • 3.1 队列的链式存储结构
      • 3.2 队列的常见接口
      • 3.3 队列的接口实现
        • 初始化
        • 判空
        • 入队列
        • 出队列
        • 获取队头元素
        • 获取队尾元素
        • 获取节点个数
        • 销毁
      • 3.4 源代码
    • 4、队列的顺序存储(循环队列)

1、队列的概念

队列是一种先进先出(First In First Out ,FIFO)的数据结构,可以简单理解为排队的概念。在队列中,数据项按照插入的顺序排列,并且只能在队列的一端插入(称为队尾),在另一端删除(称为队头)。

2、队列的结构

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

在这里插入图片描述

如何选择合适的数据结构实现队列(数组or链表)

在前面学习的顺序表中,我们知道数组只有在尾插和尾删效率高为O(1),当需要对头部元素操作时效率较低为O(n)。队列的特点是在队尾插入元素,在队头删除元素,序列两端都需要访问,这就导致使用数组实现队列时必定有一端的插入(or删除)效率低,因此不建议使用数组实现队列

3、队列的链式存储

通过上面的分析,我选择链式存储结构来实现队列。这是因为链式存储结构实现两端的高效访问很简单——只需要增加一个尾指针即可实现两端的O(1)访问

3.1 队列的链式存储结构

定义两个结构体

  • QNode:保存队列中节点的元素数据下一个节点
  • Queue:保存头指针尾指针队列中有效元素个数
typedef int QDateType;
typedef struct QueueNode
{QDateType val;//当前节点的数据struct QueueNode* next;//当前节点的下一个节点
}QNode;typedef struct Queue
{QNode* phead;//头指针QNode* ptail;//尾指针int size;//记录队列有效元素个数
}Queue;

3.2 队列的常见接口

//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);//入队列
void QueuePush(Queue* pq,QDateType x);//出队列
void QueuePop(Queue* pq);
//获取队头元素
QDateType QueueFront(Queue* pq);
//获取队尾元素
QDateType QueueBack(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取有效元素个数
int QueueSize(Queue* pq);

3.3 队列的接口实现

初始化

头尾指针置空,队列有效元素个数初始化为0

void QueueInit(Queue* pq)
{assert(pq);//哨兵位可选可不选(可以有也可以没有)pq->phead = pq->ptail = NULL;pq->size = 0;
}
判空

直接返回Queue结构体保存的size即可

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
入队列

队尾入队步骤

(1)申请新节点并初始化该节点(将x赋值,下一个节点置空)
(2)判断是否存在尾节点(队列是否为空

  • 存在尾节点(队列不为空):只需将新节点接到队尾,尾指针后移一位即可。
  • 不存在尾节点(队列为空):改变队头和队尾的值即可

(3)队列有效节点个数加1

void QueuePush(Queue* pq, QDateType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));//申请新节点if (newnode == NULL){perror("malloc fail");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++;
}
出队列

(1)判空(队列不为空才能出队)
(2)判断队列有效节点的个数

  • 一个节点:释放该节点,将头尾指针置空
  • 多个节点:定义临时QNode类型变量保存头节点的下一个节点,释放头节点,头节点更新为保存的节点

(3)队列有效节点个数减1

void QueuePop(Queue* pq)
{assert(pq);//三种情况:0个节点,1个节点,多个节点//0个assert(pq->phead);//暴力检查//if (pq->phead == NULL) return;//温柔检查//队列只有1个有效节点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--;
}
获取队头元素

断言判断是否存在头节点,如果存在直接返回头节点的值即可

QDateType QueueFront(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->phead);return pq->phead->val;
}
获取队尾元素

断言判断是否存在尾节点,如果存在直接返回尾节点的值即可

QDateType QueueBack(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->ptail);return pq->ptail->val;
}
获取节点个数

返回size即可

int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
销毁

遍历删除(释放)所有节点,最后头尾指针悬空,size置0

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

3.4 源代码

.h文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDateType;typedef struct QueueNode
{QDateType val;struct QueueNode* next;
}QNode;
入队
为什么需要两个指针
//void QueuePush(QNode** head,QNode** ptail);
//
出队
//void QueuePop(QNode** head);typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;//初始化
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);//入队列
void QueuePush(Queue* pq,QDateType x);//出队列
void QueuePop(Queue* pq);QDateType QueueFront(Queue* pq);
QDateType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);

.c文件

#include "Queue.h"//初始化
void QueueInit(Queue* pq)
{assert(pq);//哨兵位可选可不选pq->phead = 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 = pq->ptail = NULL;pq->size = 0;
}//入队列
void QueuePush(Queue* pq, QDateType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");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++;
}//出队列
void QueuePop(Queue* pq)
{assert(pq);//三种情况:0个节点,1个节点,多个节点//0个assert(pq->phead);//暴力检查//if (pq->phead == NULL) return;//温柔检查//1个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--;
}QDateType QueueFront(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->phead);return pq->phead->val;
}
QDateType QueueBack(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->ptail);return pq->ptail->val;
}
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}

4、队列的顺序存储(循环队列)

虽然队列的一般实现使用链式存储,但是也有一些情况可以使用数组存储,比如循环队列。
具体可以查看这篇博客———循环队列OJ

END

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

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

相关文章

k8s持久化存储PV和PVC

一、PV和PVC 1.PersistentVolume (PV) PersistentVolume (PV) 是外部存储系统中的⼀块存储空间&#xff0c;由管理员创建和维护。与 Volume⼀样&#xff0c; PV 具有持久性&#xff0c;⽣命周期独⽴于 Pod&#xff1b; 2.PersistentVolumeClaim (PVC) PersistentVolumeClaim…

散点图、折线图 -- 通过javascript实现

散点图 散点图适合用于探索数据大局、比较值、发现趋势、模式和变量间关系&#xff0c;是数据分析中直观展示和初步探索的有力工具。 代码&#xff1a; <!DOCTYPE html> <html> <script src"https://cdn.plot.ly/plotly-latest.min.js"><…

如何快速实现MODBUS TCP转Profinet——泗博网关EPN-330

泗博网关EPN-330可作为PROFINET从站&#xff0c;支持与西门子S7-200 SMART/300/400/1200/1500全系列PLC以及具有PROFINET主站的系统无缝对接&#xff0c;而Modbus TCP端&#xff0c;可以与Modbus TCP从站设备、主站PLC、DCS系统以及组态软件等进行数据交互。 通过EPN-330&…

SemanticKernel/C#:实现接口,接入本地嵌入模型

前言 本文通过Codeblaze.SemanticKernel这个项目&#xff0c;学习如何实现ITextEmbeddingGenerationService接口&#xff0c;接入本地嵌入模型。 项目地址&#xff1a;https://github.com/BLaZeKiLL/Codeblaze.SemanticKernel 实践 SemanticKernel初看以为只支持OpenAI的各…

近似算法:求Π的近似值(迭代法)

问题&#xff1a;请用正多边形逼近法求Π的近似值。 算法&#xff1a;圆的周长 正多边形的边长 * 边数。设圆的半径为1&#xff0c;则2Π i * x 。其中 i 为正多边形边数&#xff0c;x 为边长。 因为圆的半径 内接于此圆的正六边形的边长&#xff0c;故从六边形开始计算。参…

git系统学习

git系统学习 git命令行获取git 版本号 创建初始版本库创建git库初始化用户名和密码查看用户名和邮箱修改用户名和密码 将文件添加到版本库中删除暂存文件提交代码查看提交信息查看更加详细的信息查看提交差异版本库内文件的删除和重命名删除库里的文件重命名库里的文件 打标签查…

重启人生计划-大梦方醒

&#x1f973;&#x1f973;&#x1f973; 茫茫人海千千万万&#xff0c;感谢这一刻你看到了我的文章&#xff0c;感谢观赏&#xff0c;大家好呀&#xff0c;我是最爱吃鱼罐头&#xff0c;大家可以叫鱼罐头呦~&#x1f973;&#x1f973;&#x1f973; 从今天开始&#xff0c;我…

MybatisPlus——扩展功能(一)

扩展功能 1.代码生成 在使用MybatisPlus以后&#xff0c;基础的Mapper、Service、PO代码相对固定&#xff0c;重复编写也比较麻烦。因此MybatisPlus官方提供了代码生成器根据数据库表结构生成PO、Mapper、Service等相关代码。只不过代码生成器同样要编码使用&#xff0c;也很麻…

软考高级:真实的程序、核心程序、小型基准程序、合成基准程序

一、AI 讲解 这段内容描述了在软件测试或性能测试中&#xff0c;不同类型程序的测试精确度排名。 测试类型说明精确度排名真实的程序直接测试实际运行的软件或系统&#xff0c;能够反映真实的使用场景1核心程序测试系统或应用的核心模块或功能&#xff0c;虽然范围较小但仍具…

使用Selenium调试Edge浏览器的常见问题与解决方案

背景介绍 在当今互联网时代&#xff0c;网页爬虫已经成为数据获取的重要手段。而Selenium作为一款功能强大的自动化测试工具&#xff0c;被广泛应用于网页爬取任务中。虽然Chrome浏览器是Selenium用户的常见选择&#xff0c;但在某些工作环境中&#xff0c;我们可能需要使用Ed…

运行时数据区

运行时数据区 方法区 Method Area&#xff0c;用于存储已被虚拟机加载的类信息&#xff08;、、&#xff09;、常量、静态变量、即时编译后的代码等数据线程公用类信息 类型信息&#xff1a;类class、接口interface、注解annotation、枚举enum域Field信息&#xff1a;字段名称、…

某MDM主数据管理系统与微软Dynamic CRM系统(新加坡节点)集成案例

一、项目背景 某客户需要将物料和配件等主数据和海外系统进行对接&#xff0c;由SAP PO在中间对接海外系统&#xff0c;进行主数据的下发&#xff0c;方便两端系统之间进行对接&#xff0c;集团统一性管理国内海外数据&#xff0c;提高整体业务效率&#xff0c;保证数据的时…

基于Java中的SSM框架实现在线收银系统项目【项目源码+论文说明】

基于Java中的SSM框架实现在线收银系统演示 摘要 科技的力量总是在关键的地方改变着人们的生活&#xff0c;不仅如此&#xff0c;我们的生活也是离不开这样或者那样的科技改变&#xff0c;有的消费者没有时间去商场购物&#xff0c;那么电商和快递的结合让端口到消费者的距离不…

气膜建筑的抗风与防火性能:保障仓储的安全—轻空间

气膜建筑以其独特的结构和材料优势&#xff0c;为仓储设施提供了可靠的安全保障。在应对自然灾害特别是强风和火灾时&#xff0c;气膜建筑展示了优异的抗风和防火性能。轻空间将详细探讨这些性能及其在实际应用中的表现。 气膜建筑的抗风能力源于其特殊的结构设计和高性能材料。…

ZLM+wvp-pro使用错误记录

这里千万不要写127.0.0.1 在同步国标同步的时候&#xff0c;会出现接口不可达。以下是抓包工具抓的内容 这个时候就很奇怪了&#xff0c;这是为什么呢&#xff0c;这个时候我们通过telnet来判断一下&#xff0c;会发现端口占用&#xff0c;那么这个时候为什么说端口不可达。。。…

一站搞定原型链:深入理解JavaScript的继承机制

目录 一站搞定原型链&#xff1a;深入理解JavaScript的继承机制 一、基本概念 1. 对象与原型 2. 构造函数 二、原型链 三、原型链的终点 四、原型链的构造 1. 创建对象 2. 原型对象的原型 五、继承 1. 原型继承 2. Class 语法糖 六、总结 作者&#xff1a;watermel…

冥想第一千二百四十八天(12478)

1.今天周日&#xff0c;被今天的天气治愈了&#xff0c;空气特别的好。 2.先去游泳了1个小时&#xff0c;中午和家人一起吃饭。 3.下午没再出去了。给溪溪桐桐洗了澡。 4.感谢父母&#xff0c;感谢朋友&#xff0c;感谢家人&#xff0c;感谢不断进步的自己。

Linux应用层开发(7):网络编程

互联网对人类社会产生的巨大变革&#xff0c;大家是有目共睹的&#xff0c;它几乎改变了人类生活的方方面面。互联网通信的本质是数字通信&#xff0c;任何数字通信都离不开通信协议的制定&#xff0c;通信设备只有按照约定的、统一的方式去封装和解析信息&#xff0c;才能实现…

STM32的USB接口介绍

STM32 USB接口是STM32微控制器系列中集成的一种通信接口&#xff0c;它允许STM32微控制器与外部设备或计算机进行高速的数据传输和通信。以下是STM32 USB接口的简要介绍&#xff1a; 1. 接口类型 STM32的USB接口通常支持USB 2.0标准&#xff0c;部分高端型号可能还支持USB 3.…

LVS负载均衡集群部署之—NAT模式的介绍及搭建步骤

一、环境准备 1.准备三台rhel9服务器 服务器名称 主机名 ip地址备注LVS调度服务器lvs.timinglee.org eth0:172.25.254.100&#xff08;外网&#xff09; eth1:192.168.0.100(内网) 关闭selinux和防火墙webserver2网站服务器webserver1.timinglee.orgeth0&#xff1a;192.168.…