数据结构入门:队列

news2024/12/30 3:25:36

目录

文章目录

前言

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一次),每个节点都是相对独立的空间,所以需要一个个的遍历逐个销毁。


总结

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

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

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

相关文章

“大数据杀熟”,原来是这样的

前几天和朋友去看电影,票是各自买的,买了票才发现自己比朋友买的票贵。一问才知道,朋友是新注册的账号,价格比我的便宜不少。 这就让我想起来之前看到的一个词“大数据杀熟”。 说现在一些互联网平台和商家已经成佛了&#xff0…

时序预测 | MATLAB实现EEMD-LSTM、LSTM集合经验模态分解结合长短期记忆神经网络时间序列预测对比

时序预测 | MATLAB实现EEMD-LSTM、LSTM集合经验模态分解结合长短期记忆神经网络时间序列预测对比 目录 时序预测 | MATLAB实现EEMD-LSTM、LSTM集合经验模态分解结合长短期记忆神经网络时间序列预测对比效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 时序预测 | …

css中的var函数

css中的var函数 假设我们在css文件存在多个相同颜色值,当css文件越来越大的时候,想要改颜色就要手动在每个旧颜色上修改,这样维护工作非常难进行。 但是我们可以使用变量来存储值,这样可以在整个css样式表中重复使用&#xff0c…

halo --- 上传图片服务器错误

文章目录 问题定位过程1、查看日志 报错的是数据库操作异常2、再次上传一张小一点的图片3、检查nginx的配置文件 原因解决 问题 上传图片时,报错服务器错误(包括上传附件、博客文章插入图片、上传相册) 定位过程 1、查看日志 报错的是数据库…

GEE学习04-

0 回顾 之前学习的内容可以概括为: conda activate gee cd /d e:/geelearn jupyter lab可以在prompt中chrlc停止当前打开的jupyter lab. import ee #ee.Authenticate() import geemap geemap.set_proxy(port 1080) map geemap.Map() map1、视频课学习 之后跟着…

前端技术Vue学习笔记--003

前端技术Vue学习笔记 文章目录 前端技术Vue学习笔记1、Vue生命周期和生命周期的四个阶段1.1、Vue生命周期1.2、生命周期的四个阶段1.3、Vue生命周期函数<font colorred>&#xff08;钩子函数&#xff09; 2、小黑记账本&#xff08;案例&#xff09;3、工程化开发和脚手架…

python-02(入门基础篇2——基本常见语法)

python-02&#xff08;入门基础篇2——基本常见语法&#xff09; 1. 逻辑判断词1.1 布尔类型1.1.1 python为False的情况 1.2 逻辑判断词 not 2. for 语句2.1 语法结构2.2 例子2.2.1 例子1——循环迭代字符串2.2.2 例子2——进行数值循环2.2.2.1 简单循环&#xff08;结合range函…

从Spring源码看创建对象的过程

从Spring源码看创建对象的过程 Spring对于程序员set注入的属性叫做属性的填充、对于set注入之后的处理&#xff08;包括BeanPostProcessor的处理、初始化方法的处理&#xff09;叫做初始化。 研读AbstractBeanFactory类中的doGetBean()方法 doGetBean()方法首先完成的工作是…

MySQL高级-锁+mysql的主从关系(详解02)

目录 1.锁 1.1.Mysql锁问题 1.1.1.锁概述 1.1.2.锁分类 1.1.3.Mysql 锁 1.2.MyISAM 表锁 1.2.1.如何加表锁 1.2.2.读锁案例 1.2.3.写锁案例 1.3.InnoDB 行锁 支持事务 1.3.1.行锁介绍 1.3.2.背景知识 1.3.3.InnoDB 的行锁模式 1.3.4.案例准备工作 innodb 支持事务…

虚幻引擎游戏开发过程中,游戏鼠标如何双击判定?

UE虚幻引擎对于游戏开发者来说都不陌生&#xff0c;市面上有47%主机游戏使用虚幻引擎开发游戏。作为是一款游戏的核心动力&#xff0c;它的功能十分完善&#xff0c;囊括了场景制作、灯光渲染、动作镜头、粒子特效、材质蓝图等。本文介绍了虚幻引擎游戏开发过程中游戏鼠标双击判…

计算机网络实验4:HTTP、DNS协议分析

文章目录 1. 主要教学内容2. HTTP协议3. HTTP分析实验【实验目的】【实验原理】【实验内容】【实验思考】 4. HTTP分析实验可能遇到的问题4.1 捕捉不到http报文4.2 百度是使用HTTPS协议进行传输4.3 Wireshark获得数据太多如何筛选4.4 http报文字段含义不清楚General&#xff08…

spring boot 集成 jetcache【基础篇:@Cached、@CreateCache、@CacheRefresh】

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/129832925 目录 前言 版本 配置通用说明 项目结构 代码 启动类 实体类 基础使用——增删改查&#xff08;Cached、CacheInv…

github上有哪些值得读源码的react项目?

前言 下面是我整理的关于值得一读源码的react项目&#xff0c;希望对你有所帮助~ 1、 calcom Star: 21.6k calcom是一个开源的计算器应用程序。它提供了基本的数学运算功能&#xff0c;例如加法、减法、乘法和除法&#xff0c;还支持 科学计算、进制转换和单位转换等高级功能…

【刻削生千变,丹青图“万相”】阿里云AI绘画创作模型 “通义万相”测评

刻削生千变&#xff0c;丹青图“万相 4月7日&#xff0c;阿里大模型“通义千问”开始邀请用户测试体验。现阶段该模型主要定向邀请企业用户进行体验测试&#xff0c;用户可通过官网申请&#xff08;tongyi.aliyun.com&#xff09;&#xff0c;符合条件的用户可参与体验。 随…

skywalking忽略调用链路中的指定异常

文章目录 一、介绍二、演示项目介绍1. 支付服务2. 订单服务 三、项目演示1. 未忽略异常2. 忽略异常修改配置使用注解 四、结论 往期内容 一、skywalking安装教程 二、skywalking全链路追踪 三、skywalking日志收集 一、介绍 在前面介绍在微服务项目中使用skywalking进行全链…

LLaMA长度外推高性价比trick:线性插值法及相关改进源码阅读及相关记录

前言 最近&#xff0c;开源了可商用的llama2&#xff0c;支持长度相比llama1的1024&#xff0c;拓展到了4096长度&#xff0c;然而&#xff0c;相比GPT-4、Claude-2等支持的长度&#xff0c;llama的长度外推显得尤为重要&#xff0c;本文记录了三种网络开源的RoPE改进方式及相…

使用appuploader怎么安装测试​

使用appuploader怎么安装测试​ 一.安装测试​ 首先我们来看安装测试这个模块&#xff0c;注意按照上面提示内容操作。 点击首页的测试设备管理 二.选择IPA​ 进入“安装测试”页面&#xff0c;选择一个&#xff08;必须是开发类型描述文件编译&#xff0c;且描述文件包含设…

f1tenth仿真设置

文章目录 一、安装依赖二、进入工作空间克隆三、编译四、运行 一、安装依赖 tf2_geometry_msgs ackermann_msgs joy map_server sudo apt-get install ros-noetic-tf2-geometry-msgs ros-noetic-ackermann-msgs ros-melodic-joy ros-noetic-map-server 二、进入工作空间克隆…

详解Linux文本三剑客

目录 一、grep 1.什么是grep? 2.如何使用&#xff1f; 3.正则 二、sed 1.认识sed? 2.如何使用&#xff1f; 三、awk&#xff08;重点&#xff09; 1.awk变量 1.1内置变量 1.2自定义变量 2.awk数组 四、经典实战案例 案例一&#xff1a;筛选IPv4地址 案例二&am…

为MySQL新增一张performance_schema表 | StoneDB 技术分享会 #4

StoneDB开源地址 https://github.com/stoneatom/stonedb 设计&#xff1a;小艾 审核&#xff1a;丁奇、李浩 编辑&#xff1a;宇亭 作者&#xff1a;王若添 中国科学技术大学-软件工程-在读硕士、StoneDB 内核研发实习生 performance_schema 简介 MySQL 启动后会自动创建四…