数据结构——队列(Queue)

目录

1.队列的介绍

2.队列工程

2.1 队列的定义

2.1.1 数组实现队列

2.1.2 单链表实现队列

2.2 队列的函数接口

2.2.1 队列的初始化

2.2.2 队列的数据插入(入队)

2.2.3 队列的数据删除(出队)

2.2.4 取队头数据

2.2.5 取队尾数据

2.2.6 判断队列是否为空

2.2.7 队列长度统计

2.2.8 队列的销毁

 3.队列总结反思


1.队列的介绍

        队列,顾名思义,作为有素质的新时代公民,在现实生活中我们常常会遇到排队的场景,而队列就是借此种情形衍生出来的数据结构形式。在需要排队的时候,我们面对一个队列会自觉地站在队尾。随着当队伍中的人慢慢出队,我们的位置也从队尾慢慢移动到了队头,当我们成为一个队的第一个人时,我们就明白终于轮到我们出队了。队列这种数据结构组织数据的形式和排队的场景十分相似,均为先进先出,后进后出的规则。

        在掌握了栈这种数据结构的基础之上,我们再来学习队列会比较轻松。栈主要实现的是“先进后出,后进先出”的规则,而队列遵循的则是“先进先出,后进后出”的规律。因此我们可以相互类比地进行学习。

2.队列工程

2.1 队列的定义

        在创建队列之前,我们需要考虑队列用什么方式实现。我们依然从数组和链表两种结构去考虑优劣,我们发现队列在出队和访问时需要访问队头,在入队时需要找到队尾,所以我们根据这一特征仔细分析一下队列最合适的实现方式。

2.1.1 数组实现队列

        当我们打算用数组实现队列的时候:

        如果以下标小的一端为队头,我们发现在入队时,我们很容易可以在队尾插入数据。但是在出队的时候,类似于顺序标的头删操作,所有数据前移一位,需要O(n)的时间复杂度。

        如果以下标大的一端为队头,在出队是很容易。但是在入队时同样需要依次挪动数据,也导致了O(n)的时间复杂度。

2.1.2 单链表实现队列

        当使用单链表的时候,头删头插数据很容易,但是尾插尾删因为需要遍历链表找尾而变得复杂。这是我们只需要再引入一个指针指向单链表的尾即可解决这个问题。因为将单链表用作队列的时候,队列只会对队头和队尾进行操作,所以无论哪一边为队头,队列实际操作的都只有链表的头结点和尾结点,所以我们只需要定义指针指向头和尾即可避免遍历的冗余操作。

        弄明白这一点后,我们再来详细讨论一下到底以单链表的哪一边为队头,哪一边为队尾。

        如果以单链表头结点为队头,以尾结点为队尾。在入队的时候我们需要将数据插入队尾,也即在尾结点后插入数据,因为我们提前存储了尾结点位置,所以可以直接将新结点链接在尾结点后。在出队的时候,就相当于删除队头的结点,也就是单链表头删,也没有问题。看来这种方案是个不错的选择。

        如果以单链表头结点为队尾,以尾结点为队头。那么在入队的时候,我们需要将数据插入队尾,也就是单链表头插,我们可以做到直接链接。在出队的时候,我们需要删除队头的数据,即单链表尾删,熟悉单链表的小伙伴们都知道,单链表尾删是需要尾结点前一个结点的(需要改变倒数第二个结点的next,使其为空指针),所以在选取这种方式时,我们使用指针指示的就不该是尾结点了,而应该是尾结点的前一个结点。

        在这篇博客中,我们采取第一种方式(单链表头结点为队头,以尾结点为队尾)。

typedef int QDataType;typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;

        首先定义出单链表的结点结构体,然后再定义出队列的结构体,队列结构体之中看似有三个成员,实际上都是对队列载体——单链表的信息描述,分别是链表头结点(队头),链表尾结点(队尾),链表节点个数(队列长度)。

2.2 队列的函数接口

2.2.1 队列的初始化

        新建了一个队列后,我们首先需要对其进行初始化,将队列结构体中队头、队尾指针置空,将size置为0。

void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}

2.2.2 队列的数据插入(入队)

        通过我们刚才的分析,入队可以简单的视为尾插,所以我们按照尾插的逻辑来写入队函数即可。

        首先需要开辟空间创建新结点,然后熟悉单链表的小伙伴又知道了,在我们链接结点之前需要对特殊情况进行特殊处理。一般而言,单链表的特殊情况就是空链表和只有一个结点的链表。当链表为空时,队列中phead和ptail指针均为空指针,直接链接肯定会出错,所以当为空链表时,需要特殊处理一下。当链表仅有一个结点时,其ptail就是尾结点,所以不需要特殊考虑,和其余情况一样,可以直接链接。

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

2.2.3 队列的数据删除(出队)

        出队操作在这里就相当于头删。对于删除操作我们要做最基本的判断排除空链表的情况,这里我使用了assert断言。然后考虑特殊情况,当链表只有一个结点时,头删后链表为空,队头指针和队尾指针都需要置空,其余情况都是只需要改变队头指针即可。

void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);QNode* del = pq->phead;if (pq->phead == pq->ptail){pq->phead = pq->ptail = NULL;}else{pq->phead = pq->phead->next;}free(del);del = NULL;pq->size--;
}

2.2.4 取队头数据

        很简单的操作,取出队头指针所指结点的保存的值即可。

QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}

2.2.5 取队尾数据

        取队尾数据在某些场景下会被使用,其方法和取队头数据一样。

QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}

2.2.6 判断队列是否为空

        队列为空的特征很多,包括队头指针、队尾指针为空,队列长度为0,任取一个作为判断依据即可。

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}

2.2.7 队列长度统计

        队列的长度由成员size指出,将其作为返回值即可。

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

2.2.8 队列的销毁

        队列实际上是一个链表+一个记录链表信息的结构体,所以在销毁链表的时候,我们需要按照销毁单链表的方式先释放单链表所占用的空间,然后将记录信息的结构体其中的值置0、指针置空,防止野指针。

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

 3.队列总结反思

        栈和队列都是比较简单的数据结构,分别采取数组和链表实现了“先进后出,后进先出和“先进先出,后进后出”的功能。只要能熟练的控制应用单链表,我觉得队列应该不在话下。队列在具体实际中的用途也很广泛,在广度优先搜索中队列会作为数据存储方式,对所有出现的情况进行记录与拓展。

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

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

相关文章

python匹配问题

脏数据匹配 一般数据建模步骤中,数据清洗耗时占比80%以上,因为现实中接触到的数据相当脏,无法直接简单的用pandas的merge函数解决。下面以QS大学排名的匹配为例,简单介绍脏数据匹配中会遇到的问题和主要步骤。 1 问题描述 给定…

Vue.js设计与实现阅读2

Vue.js设计与实现阅读-2 1、前言2、框架设计的核心要素2、1 提升用户体验2、2 控制代码体积2、3 Tree-Shaking2、4 特性开关2、5 错误处理 1、前言 上一篇我们了解到了 命令式和声明式的区别,前者关注过程,后者关注结果了解了虚拟dom存在的意义&#x…

Java后端开发——SSM整合实验

文章目录 Java后端开发——SSM整合实验一、常用方式整合SSM框架二、纯注解方式整合SSM框架 Java后端开发——SSM整合实验 一、常用方式整合SSM框架 1.搭建数据库环境:MySQL数据库中创建一个名称为ssm的数据库,在该数据库中创建一个名称为tb_book的表 …

如何顺滑使用华为云编译构建平台?

这两年平台构建服务需求越来越大,却一直苦于找不到一些指南, 这里特意写了一篇, 对在学习代码阶段和新手程序员朋友也蛮友好, 配置真的也不难, 也特别适合想尝试从0到1做个APP的朋友了。 以华为云的CodeArts Build为例…

OpenBLAS 的静态库命名分析 — — 以 x86_64 的静态库为例

在不同的机器上,生成的openblas生成的lib的名字可能是这样的: libopenblas_skylakexp-r0.3.26.dev.a libopenblas_skylakexp-r0.3.26.dev.so 也可能是这样的: liblapack_static_haswellp-r0.3.25.dev.a libopenblas_haswellp-r0.3.26.dev…

Linux-添加虚拟内存,不添加硬盘方式操作

在linux中,当物理内存mem不足时,就会使用虚拟内存(swap分区) 例如增加2G虚拟内存,操作如下: 1.查看内存大小 [rootlocalhost ~]# free -m 2.创建要作为swap分区的文件:增加1GB大小的交换分区,则命令写法如下,其中的cou…

1. 认识SPSS

使用的是IBM SPSS statistics 25,参考教材《统计分析与SPSS的应用》 一、安装和启动 具体安装过程是参考spss下载以及安装详细教程这篇文章,下载安装包然后按他的步骤获取用户许可证即可。 二、主要窗口 数据编辑器窗口data editor 是SPSS的主程序窗…

ssm基于Vue的戏剧推广网站论文

摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统戏剧推广信息管理难度大,容错率低&#xff0c…

代码随想录day23 二叉岁终章

669. 修剪二叉搜索树 题目 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。 思考 这题有个…

2024年中职网络安全——Windows操作系统渗透测试(Server2105)

Windows操作系统渗透测试 任务环境说明: 服务器场景:Server2105服务器场景操作系统:Windows(版本不详)(封闭靶机)需要环境加Q 目录 1.通过本地PC中渗透测试平台Kali对服务器场景进行系统服务…

Docker 部署后端项目自动化脚本

文章目录 开机自启动docker打包后端项目Dockerfile文件脚本文件使用 开机自启动docker systemctl enable dockersystemctl is-enabled docker打包后端项目 这里的项目位置是target同级目录 1.在项目下面新建一个bin目录 新建一个package.txt 写入下方代码后 后缀改为.bat ec…

配置git服务器

第一步: jdk环境配置 (1)搜索【高级系统设置】,选择【高级】选项卡,点【环境变量】 (2)在【系统变量】里面,点击【新建】 (3)添加JAVA_HOME环境变量JAVA_HO…

小程序学习基础(页面加载)

打开首页&#xff0c;然后点击第一个按钮进去心得页面 进入心得页面以后 第一个模块是轮播图用的是swiper组件&#xff0c;然后就是四个按钮绑定点击事件&#xff0c;最后就是下拉刷新&#xff0c;下拉滚动&#xff0c;上拉加载。代码顺序wxml,js,wcss,json。 <!--pages/o…

【开源商城推荐-LGPL-3.0】ts-mall 聚惠星商城

dts-shop: 聚惠星商城 DTS-SHOP&#xff0c;基于 微信小程序 springboot vue 技术构建 &#xff0c;支持单店铺&#xff0c;多店铺入驻的商城平台。项目包含 微信小程序&#xff0c;管理后台。基于java后台语言&#xff0c;已功能闭环&#xff0c;且达到商用标准的一套项目体…

金和OA C6 MailTemplates.aspx SQL注入漏洞

文章目录 产品简介漏洞概述指纹识别漏洞利用修复建议 产品简介 金和OA协同办公管理系统软件&#xff08;简称金和OA&#xff09;&#xff0c;本着简单、适用、高效的原则&#xff0c;贴合企事业单位的实际需求&#xff0c;实行通用化、标准化、智能化、人性化的产品设计&#…

Day05

19.用户与权限管理 19.1 用户管理 MySQL用户可以分为普通用户和root用户。root用户是超级管理员&#xff0c;拥有所有权限&#xff0c;包括创建用户、删除用户和修改用户的密码等管理权限&#xff1b;普通用户只拥有被授予的各种权限。 MySQL提供了许多语句用来管理用户账号…

php 的数据类型

目录 1.整型 2.浮点型 3.布尔类型 4.字符串 5.数组 6.NULL 7.对象 8.资源类型 查看变量对应值的类型&#xff1a; 1.使用“gettype(传入一个变量var)”来显示变量var的类型; 只会显示类型 2.使用“var_dump(传入一个变量var)”来显示变量var的类型; 会显示具体内容打…

5 - 视图|存储过程

视图&#xff5c;存储过程 视图视图基本使用使用视图视图进阶 存储过程创建存储过程存储过程进阶存储过程参数循环结构 视图 视图是虚拟存在的表 表头下的数据在真表里 表头下的数据存储在创建视图时 在select命令访问的真表里 优点&#xff1a; 安全数据独立简单 用户无需关…

ADS仿真 之 容差/良率分析

之所以要进行容差分析&#xff0c; 是因为任何电子元器件均存在一定的误差&#xff0c; 如电感、电容的精度等。 例如一个标称为2.0nH0.1nH的电感&#xff0c;代表的意思产品有99.74%的概率落在2.0nH0.1nH范围内&#xff0c; 即满足6σ &#xff0c;σ是标准偏差或者说方差&…

Hyperledger Fabric 二进制安装部署 Peer 节点

规划网络拓扑 3 个 orderer 节点&#xff1b;组织 org1 , org1 下有两个 peer 节点&#xff0c; peer0 和 peer1; 组织 org2 , org2 下有两个 peer 节点&#xff0c; peer0 和 peer1; 节点宿主机 IPhosts端口cli192.168.1.66N/AN/Aorderer0192.168.1.66orderer0.example.com70…