数据结构线性表——队列

前言:哈喽小伙伴们,这篇文章我们继续来学习线性表的第五章——队列。

世上无难事,只怕有心人。数据结构看似有很多种类型,但是它们之间都有着千丝万缕的联系。

只要我们能够耐心学习思考,就一定能够将知识串通起来,轻松拿下。


目录

一.什么是队列

二.队列的实现

三.队列的操作

1.队列初始化

2.入队

3.出队

4.队列长度

5.队头数据

6.队尾数据

7.判断空队列

8.销毁队列

9.测试

四.完整代码展示

1.Queue.h

2.Queue.c

五.总结


一.什么是队列

队列和栈一样,也是一种特殊的线性表,不同于栈的是:

队列要求数据只能从一端插入,从另一端删除。因此队列具有先进先出的特点,就类似于我们生活中的排队

那么关于队列也有两个专用名词:

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


二.队列的实现

根据我们现在对队列的了解,要实现一个好的队列,就需要在头删和尾插上更加便捷

所以我们首先排除使用数组,头删比较麻烦,那么就在单链表和双链表里选。

双链表无论是实现栈还是队列都可以,但是都有点小题大作,仅仅是对头尾的单独操作,不需要使用两个指针,所以队列我们选择用单链表实现。

typedef int QDataType;

typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;

但是这样的实现方法有一个问题,就是必须要使用二级指针才能对队列进行操作

但是我们不喜欢用二级指针,该怎么避免使用呢??? 

其实很简单,如果是对结构体里的数据进行操作,我们只需要用结构体类型的一级指针即可,所以我们再定义一个嵌套结构体,单独用来记录队列的头、尾,就可以使用一级指针来操作啦

typedef int QDataType;

typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

同时我们为了方便记录队列长度,额外定义size变量


三.队列的操作

1.队列初始化

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

2.入队

//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush->malloc");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

入队,实际上就是尾插

值得注意的一点是,我们要考虑一下队列是否为空

因为如果队列为空,那么入队之后,对头和队尾都需要指向该数据,但是如果队列已经存在数据,那就只需要让原队尾指向新数据,再让新数据称为队尾即可


3.出队

//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	//判空
	assert(pq->phead);
	QNode* head = pq->phead;
	pq->phead = pq->phead->next;
	free(head);
	head = NULL;
	if (pq->phead == NULL)
	{
		pq->ptail = NULL;
	}
	pq->size--;
}

出队,也就是头删

删除数据肯定首先断言是否为空队列

其次在考虑,如果只有一个数据,删除之后,队列为空,但是好像ptail还指向该数据的空间,这样ptail就变成了野指针。所以要进行一次判断,让phead和ptail都要指向NULL

那么判断条件就是队头是否为空,为空就说明队列为空。

接下来的操作就都很简单啦,博主将直接展示代码


4.队列长度

//队列长度
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

5.队头数据

//队头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->data;
}

6.队尾数据

//队尾数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->data;
}

7.判断空队列

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

这里是一个技巧,如果phead为空就说明是空队列,返回false,反之返回true。 


8.销毁队列

//销毁
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;
}

9.测试

int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	int size = QueueSize(&q);
	printf("size = %d\n", size);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	QueueDestroy(&q);
	return 0;
}

这里博主尽可能多的展示了大部分操作,其他操作就靠小伙伴们下去自己制作并测试啦。

结果如下:


四.完整代码展示

1.Queue.h

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int QDataType;

typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//初始化
void QueueInit(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//队长
int QueueSize(Queue* pq);
//队头数据
QDataType QueueFront(Queue* pq);
//队尾数据
QDataType QueueBack(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);

2.Queue.c

#include "Queue.h"

//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush->malloc");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	//判空
	assert(pq->phead);
	QNode* head = pq->phead;
	pq->phead = pq->phead->next;
	free(head);
	head = NULL;
	if (pq->phead == NULL)
	{
		pq->ptail = NULL;
	}
	pq->size--;
}
//队列长度
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//队头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->data;
}
//队尾数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->data;
}
//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}
//销毁
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;
}

五.总结

队列也是在单链表的基础上进行另类操作,没有附加其他实质性有难度的地方,所以相信大家只要掌握好了单链表的知识,对于队列的理解和实现也是不在话下。

喜欢博主文章的小伙伴记得多多支持一键三连哦!!!

我们下期再见!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一例plugx样本的分析(AcroRd32cWP)

这是一例plugx的样本&#xff0c;使用了一个合法签名的程序 &#xff0c;使用侧加载的方式加载一个恶意的dll&#xff0c;解密一个dat文件来&#xff0c;在内存中执行一个反射型dll来完成恶意功能。 这个病毒会使用摆渡的方式的来窃取内网的文档数据&#xff0c;具有严重的失泄…

c语言11周(16~20)

利用函数求和 //只填写要求的函数 double fun(int n) {double s 0;int i;for (i 1; i < n; i) {s 1.0 / (i * i);}return s; } 编写char fun(char c)函数&#xff0c;将数字参数字符c按如下规则转换。 题干编写char fun(char c)函数&#xff0c;将数字参数字符c按如…

YOLO目标检测——苹果数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;监测果园中苹果的生长情况、水果品质监控、自动化分拣数据集说明&#xff1a;苹果检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(…

《视觉SLAM十四讲》-- 后端 1(上)

文章目录 08 后端 18.1 概述8.1.1 状态估计的概率解释8.1.2 线性系统和卡尔曼滤波&#xff08;KF&#xff09;8.1.3 非线性系统和扩展卡尔曼滤波&#xff08;EKF&#xff09;8.1.4 小结 08 后端 1 前端视觉里程计可以给出一个短时间内的轨迹和地图&#xff0c;但由于不可避免的…

项目经理为什么要考PMP?PMP考试条件有哪些?

考得PMP&#xff0c;项目经理可以有以下收获&#xff1a; 1、面试条件上&#xff1a;有PMP证书优先&#xff1b; 2、覆盖行业和职位范围广&#xff0c;医疗&#xff0c;互联网&#xff0c;机械&#xff0c;建筑金融&#xff0c;汽车&#xff0c;零售等各行各业&#xff0c;基…

【FastCAE源码阅读9】鼠标框选网格、节点的实现

一、VTK的框选支持类vtkInteractorStyleRubberBandPick FastCAE的鼠标事件交互类是PropPickerInteractionStyle&#xff0c;它扩展自vtkInteractorStyleRubberBandPick。vtkInteractorStyleRubberBandPick类可以实现鼠标框选物体&#xff0c;默认情况下按下键盘r键开启框选模式…

qt之扫码枪编码自动识别文本

一、前言 使用扫码枪输入扫码后&#xff0c;自动将编码转为文字或识别进入下一功能。 只是简单的实现了一种方式&#xff0c;并不适用于商业用途 二、环境 扫码枪免驱自动扫码编码打印到输入库的环境下 三、正文 本文介绍也是输入一种方式&#xff0c;不限于非得扫码识别…

YOLO-NAS:最高效的目标检测算法之一

YOLO-NAS目标检测 介绍 YOLO&#xff08;You Only Look Once&#xff09;是一种目标检测算法&#xff0c;它使用深度神经网络模型&#xff0c;特别是卷积神经网络&#xff0c;来实时检测和分类对象。该算法首次在2016年的论文《You Only Look Once&#xff1a;统一的实时目标检…

【Proteus仿真】【51单片机】拔河游戏设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用按键、LED、动态数码管模块等。 主要功能&#xff1a; 系统运行后&#xff0c;指示灯处于中间位置&#xff0c;数码管显示得分0&#xff0c;当按下…

c++范围for语句

语法格式 for(declaration:expression)statement 基本使用 遍历输出 vector<int> nums { 1,2,3,4,5}; for (int num : nums) {num;cout << num << " "; } cout << endl; 遍历时修改 vector<int> nums { 1,2,3,4,5}; for (int&…

Android 布局优化,看过来 ~

屏幕刷新机制 基本概念 刷新率&#xff1a;屏幕每秒刷新的次数&#xff0c;单位是 Hz&#xff0c;例如 60Hz&#xff0c;刷新率取决于硬件的固定参数。帧率&#xff1a;GPU 在一秒内绘制操作的帧数&#xff0c;单位是 fps。Android 采用的是 60fps&#xff0c;即每秒 GPU 最多…

[文件读取]cuberite 文件读取 (CVE-2019-15516)

1.1漏洞描述 漏洞编号CVE-2019-15516漏洞类型文件上传漏洞等级⭐⭐⭐漏洞环境VULFOCUS攻击方式 描述: Cuberite是一款使用C语言编写的、轻量级、可扩展的多人游戏服务器。 Cuberite 2019-06-11之前版本中存在路径遍历漏洞。该漏洞源于网络系统或产品未能正确地过滤资源或文件路…

苍穹外卖项目笔记(1)

前言 苍穹外卖项目笔记附代码&#xff0c;贴上 github 链接&#xff0c;持续更新中&#xff1a;GitHub - Echo0701/sky-take-out &#xff08;不知道为啥发不了项目压缩包&#xff0c;那就下次再试试吧........&#xff09; 1 软件开发整体介绍 1.1 软件开发流程 1.2 角色分…

U-boot(一):Uboot命令和tftp

本文主要基于S5PV210探讨uboot。 uboot 部署&#xff1a;uboot(180~400K的裸机程序)在Flash(可上电读取)、OS在FLash(nand) 启动过程&#xff1a;上电后先执行uboot、uboot初始化DDR和Flash,将OS从Flash中读到DDR中启动OS,uboot结束 特点&#xff1a;…

MES系统如何改进生产管理?

伴随机械制造业行业竞争逐渐加剧&#xff0c;越来越多企业意识到MES系统的重要性&#xff0c;慢慢积极主动把握和实施MES系统。可是纵观绝大部分企业或者MES生产商&#xff0c;对MES的掌握依然存在比较大的分歧。 有一些人说MES系统是企业信息化构建的中枢神经&#xff0c;也有…

Oracle(2-3) Basic Oracle Net Server Side Configuration

文章目录 一、基础知识1、The Listener Process监听器进程2、Connection Methods 连接方法3、Spawn and Bequeath Conn4、Direct Hand-Off Connections 直接切换连接5、Redirection Session 重定向会话6、Simple to Complex:N-Tier 简单到复杂&#xff1a;N层7、Service Config…

SQL-LABS

less8 and 11-- 12 发现存在注入点 接下来我们会接着用联合查询 和以往的题目不一样没显错位&#xff0c;也就是没有报错的内容&#xff0c;尝试用盲注 布尔型 length&#xff08;&#xff09;返回长度 substr&#xff08;&#xff09;截取字符串&#xff08;语法substr&a…

【Linux】 ls -l 和 grep

语法:用于显示指定工作目录下之内容 ls [-alrtAFR] [name...]将 /bin 目录以下所有目录及文件详细资料列出: ls -lR /bin将 /usr/local/bin 目录以下所有有关python列出: ls -l /usr/local/bin/ | grep python在使用 ls -l 命令时&#xff0c;第一列的字符表示文件或目录的类…

计算机组成原理——指令系统题库21-40

21、假定指令地址码给出的是操作数的存储地址&#xff0c;则该操作数采用的是什么寻址。 A、 立即    B、 直接     C、 基址     D、 相对 22、寄存器间接寻址方式的操作数存储在什么中 A、 通用寄存器    B、 存储单元     C、 程序计数器     …

【C++】STL的基本用法

目录结构 1. STL概念 1.2 常见容器 1.3 六大组件 2. STL容器之vector 1. vector 2. 基本用法示例 3. STL容器之map 1. map 2. 基本用法示例 1. STL概念 C中的STL是指标准模板库的缩写。STL提供了一组通用的模板类和函数&#xff0c;用于实现常见的数据结构和算法&…