重生之我在学数据结构——队列

news2024/11/25 22:54:29

一.队列的概念

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

先进先出的概念就是先进队列的数据就会先出队列。比如入队顺序为1、2、3、4,那么出队列的顺序只有1、2、3、4这一种可能性。 

如果我们要选择结构来实现队列的话,应该选谁呢?

数组的话,因为涉及到队头出数据。数组的话,删除第一个数据的话,后面所有的数据都得往前挪,所以我们不考虑数据。

单链表的话,入数据就是尾插,出数据就是头删。队列会频繁的插入与删除数据,而链表相比于数组的有点就在于可以频繁的插入删除。所以我们可以利用单链表来实现队列。

二.队列结构的设计

队列既然要由链表实现,那么我们就要设计节点。节点只需要有数据域(保存队列待存的数据)和指针域(指向下一个节点的指针)。

在队列中,涉及的入数据和出数据分别对应着链表的头和尾,所以我们需要定义一个头节点和一个尾节点。

根据以上两点,我们可以先设计出队列节点的结构:

typedef int QueueDataType;

//队列中的节点
typedef struct QueueListNode
{
	QueueDataType a;
	struct QueueListNode* next;
}QueueNode;

而对于一条队列来说,我们需要头节点和尾节点,所以我们可以在创建一个结构体Queue,专门用来维护队列。

队列中有的接口是返回有效元素的个数,我们可以在维护队列的结构体中加一个size变量,用来记录当前队列的有效元素个数。如果不这样的话,我们就得遍历链表,会浪费时间。

//队列
typedef struct Queue
{
	QueueNode* _front;
	QueueNode* _back;
	int size;
}Queue;

三.队列的初始化和销毁

3.1队列的初始化

队列初始化,也就是对头节点和尾节点的初始化,我们开始时没有必要开辟空间,只需要在插入数据时在malloc空间即可。所以我们刚开始直接让头尾节点的指针指向NULL,size置为0。

//队列的初始化
void QueueInit(Queue* pq)
{
	assert(pq);

	pq->_front = NULL;
	pq->_back = NULL;
	pq->size = 0;
}

3.2队列的销毁

我们前面设计,由一条单链表来维护队列,所以队列的销毁其实就是链表的销毁。我们只需要遍历链表,一个节点一个节点的销毁即可。

//队列的销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);

	QueueNode* cur = pq->_front;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->_front = NULL;
	pq->_back = NULL;
	pq->size = 0;
}

四.入队列

队列插入数据的时候只能从队尾进行插入,对于单链表来说其实就是尾插。要注意的就是,每插入一个数据,size就要++。

//入队尾
void QueuePush(Queue* pq, QueueDataType x)
{
	assert(pq);

	//创建新节点
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("QueuePush()::malloc()");
		return;
	}
	newnode->a = x;
	newnode->next = NULL;

	//空队列
	if (pq->size == 0)
	{
		pq->_front = newnode;
		pq->_back = newnode;
	}
	else//非空队列
	{
		pq->_back->next = newnode;
		pq->_back = newnode;
	}

	pq->size++;
}

五.出队列

队列出数据只能从队头出数据,这样才能保证先进先出规则。而在这里其实就是头删。删除的前提是队列不为空。

头删的时候,我们只需要保存头节点的下一个节点next,然后free掉头节点,再让头节点指向head。

但是这种方式可能会造成野指针。 

当队列只有一个元素的时候,按照这种方式的确会将该节点删除,头节点置为NULL。但是指向尾节点的指针并没有改变指向,也就是说这时候为尾指针成了野指针。等到我们下一次插入数据的话,对尾指针进行解引用就会出错。

所以我们应该判断一下只有一个元素的时候,只有一个元素的时候,直接free掉头节点,然后头指针和尾指针都置为NULL。

删除之后size需要--。

//出队头
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size > 0);//队列不能为空

	//队列中只有一个元素
	if (pq->_front == pq->_back)
	{
		free(pq->_front);
		pq->_front = NULL;
		pq->_back = NULL;
	}
	else//队列有多个元素
	{
		QueueNode* next = pq->_front->next;
		free(pq->_front);
		pq->_front = next;
	}
	pq->size--;
}

六.获取队头元素

获取队头元素我们直接返回头指针指向节点的数据即可。但是要保证队列不为空。

//获取队头元素
QueueDataType GetQueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->size > 0);

	return pq->_front->a;
}

七.获取队尾元素

获取队尾元素我们直接返回尾指针指向节点的数据即可。同样要保证队列不为空。

//获取队尾元素
QueueDataType GetQueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->size > 0);

	return pq->_back->a;
}

八.获取队列有效元素个数

返回size即可。

//获取队列元素个数
int GetQueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

九.判空

判空只需要判断size是否为0即可。

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

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

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

相关文章

Vue项目实现单点登录(SSO)的逻辑和基本流程

项目集群如果一个一个登录会非常麻烦,尤其是一些大企业或者多项目使用一套体系数据的环境中,这时候登录中心也就应用而生, 今天简单说一下vue sso的实现思路,vue项目实现单点登录(SSO)通常涉及以下几个步骤…

JVM调优:根据JVM自带工具定位问题(jps、jstat、Visual VM的使用)

JVM调优步骤 发现问题、定位问题、解决问题 发现问题 常见问题如下 GC频繁CPU负载过高内存溢出(OOM)内存泄露死锁程序响应时间较长 用JDK自带命令调优工具定位问题 jps(java process status):查看正在运行的Java进程 基本语…

图解正激和Buck AC/DC转换

所谓正激式 正激方式是构造较简单,容易控制,非常普遍的方式之一。 其特征是输出功率比反激方式大,但必须加装电感和续流二极管(转流二极管:D2)。此外,和反激式相同,能利用光耦合器…

将半自动化标签绘制在原图上

用yolov8的推理,做了半自动化标签处理。 yolo的标签格式是: 标签 + 每个顶点的坐标 比如: 第一个数字0是类别,后面是每个顶点的坐标,(x,y)这样的。 而且可能是多行的 所以,要把标签画在原图上,看看打的对不对。 画标签到原图上.py import os import cv2 import n…

K3s部署及研究

这里写自定义目录标题 K3s和K8s的部署及研究Kubernetes (K8s)K3s使用场景总结1、备份系统自带yum源配置文件2、进入 /etc/yum.repos.d3、删除文件4、设置5、缓存 K3s和K8s的部署及研究 K3s 和 K8s(Kubernetes)是两个相关但不同的容器编排平台。以下是对…

43 华三AC登录Web页面

一 无线上WEB页面 1 创建vlan 56 [AC-KongZhi]vlan 56 2 退出 [AC-KongZhi-vlan56]quit 3 进入vlan三层口 配置IP地址 [AC-KongZhi]interface Vlan-interface 56 [AC-KongZhi-Vlan-interface56]ip address 192.168.56.55 24 4 在AC控制器与Host主机的接口上能通关vlan 5…

基于Nginx搭建RTMP流媒体服务器视频无法保存

文章目录 基于Nginx搭建RTMP流媒体服务器安装Nginx-RTMPNginx 配置文件 视频无法保存 基于Nginx搭建RTMP流媒体服务器 安装Nginx-RTMP 要实现RTMP流媒体服务器需要安装Nginx-RTMP模块 已有Nginx安装Nginx-RTMP模块 sudo apt update sudo apt install libnginx-mod-rtmp可能会…

心动小站Ⅰ--矢量数据库:塑造 AI 技术的新时代

前言 随着专家预测的采用率不断提高以及教育资源的引入,矢量数据库将在塑造下一个 AI 技术时代中发挥关键作用。矢量数据库相对于传统数据库的优势越来越明显,使其成为 AI 和机器学习应用不可或缺的工具。以下是矢量数据库受到关注并有望彻底改变 AI 技…

Leetcode - 周赛406

目录 一,3216. 交换后字典序最小的字符串 二,3217. 从链表中移除在数组中存在的节点 三,3218. 切蛋糕的最小总开销 I 四,3219. 切蛋糕的最小总开销 II 一,3216. 交换后字典序最小的字符串 本题要求交换一次相邻字符…

接口自动化测试框架实战-0-项目功能概览

熟悉我CSDN的朋友们应该知道,之前已经更新了requests、pytest、allure2、yaml、jenkins、postman等基础知识的合集。相信大家对接口测试已经有了全面的认识,现在应该迫不及待地想要一个实战项目了。接下来的文章中,我们将把这些知识点串联起来…

数据结构C++——栈

文章目录 一、定义二、ADT三、栈的描述方法3.1 数组描述3.1.1 派生arrayList3.1.2 定制数组arrayStack3.2 链表描述3.2.1 派生chain3.2.2 定制数组LinkedStack四、应用4.1 括号匹配4.2 汉诺塔4.3 列车车厢重排4.4 迷宫老鼠一、定义 DEF. 栈(stack)是一个线性表,其插入(也称…

Window环境下MySQL管理

1、MySQL服务启用和停止 图形化界面管理 使用键盘组合键(Win R)打开运行对话框,在对话框中输入services.msc并点击确定。 这里可以看到服务名称为MySQL84并处于正在运行的状态。 选中后右键可以进行暂停、停止、重启等操作。 命令提示符管理…

python--16 GUI编程1

GUI编程简介 主流3大GUI框架 框架名称说明Tkinter一个轻量级的跨平台图形用户界面(GUI)开发工具,是Tk图形用户界面工具包标准的Python接口Kivy基于OpenGL ES 2,能够让使用相同源代码创建的程序能跨平台运行。这个框架是事件驱动…

LLaMA 背景

什么是LLaMA? 模型介绍:LLaMA是Meta开发的语言模型,旨在推动开放科学和人工智能的实践。 参数范围:这些模型的参数数量从7B到65B不等,覆盖了不同规模的需求。 训练数据:LLaMA模型是在数万亿个公开数据集的…

2024视频改字祝福 豪车装X系统源码uniapp前端源码

源码介绍 uniapp视频改字祝福 豪车装X系统源码 全开源,只有uniapp前端,API接口需要寻找对应的。 创意无限!AI视频改字祝福,豪车装X系统源码开源,打造个性化祝福视频不再难! 想要为你的朋友或家人送上一份特别的祝福…

Spring Boot 日志 (初级)

什么是日志呢?其实就是一条条的打印语句,我们就可以根据打印出来的日志,去分析程序存在的问题等。虽然作为后端开发人员,日志并不是那么重要,但是在学习的过程中,也是比较重要的,可以使用在我们…

OpenCV分水岭算法watershed函数的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 描述 我们将学会使用基于标记的分水岭算法来进行图像分割。我们将看到:watershed()函数的用法。 任何灰度图像都可以被视为一个地形表…

vue项目实战速查记录

1.图片下载到本地 2.本地静态文件访问 3.元素大小相同,相互覆盖 1.图片下载到本地 实现原理:创建a标签,利用a标签下载属性. download(){const link document.createElement(a);link.href "图片地址";link.setAttribute(download, name);document.body.ap…

Docker核心技术:Docker原理之Namespace

云原生学习路线导航页(持续更新中) 本文是 Docker核心技术 系列文章:Docker原理之Namespace,其他文章快捷链接如下: 应用架构演进容器技术要解决哪些问题Docker的基本使用Docker是如何实现的 Docker核心技术&#xff1…

【Qt】 FFmpeg+Qt windows 32位或者64位环境搭建

简介 目前Ffmpeg官网(64位连接)下载的均为64位编译的,这要求我们采用的Qt creator也采用64位编译器。但是仍存在部分用户采用32位编译器,所以这部分用户需下载32 Ffmpeg(32位连接)。 根据使用的编译器位数…