队列详解(C语言实现)

news2024/11/29 10:37:57

文章目录

  • 写在前面
  • 1 队列的定义
  • 2 队列的初始化
  • 3 数据入队列
  • 4 数据出队列
  • 5 获取队头元素
  • 6 获取队尾元素
  • 7 获取队列元素个数
  • 8 判断队列是否为空
  • 8 队列的销毁

写在前面

本片文章详细介绍了另外两种存储逻辑关系为 “一对一” 的数据结构——栈和队列中的队列,并使用C语言实现链队列。
队列C语言实现源码:队列源码
以队列在存储数据时具有特殊的顺序规则:
队列:使用队列存储数据,遵循 “先进先出” 的原则,即最先进队列的数据最先出队列。队列也可以分为顺序队列(基于数组实现)和链队列(基于链表实现)。
在这里插入图片描述

队列的实现方式分为顺序和链式结构,分别适用于不同的场景。顺序结构在内存中占据一块连续的空间,而链式结构通过节点之间的指针连接。这使得栈和队列在实际应用中更灵活,可以根据具体需求选择不同的实现方式。

1 队列的定义

链式队列的实现其实和之前单链表的实现很类似,只不过队列中数据的进出要遵循 “先进先出” 的原则。
链式队列节点的定义:

typedef int QDataType;

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

队列的定义通常包括两个指针和一个整型,一个指针front指向队列的头,一个指针tail指向队列的尾,还有一个整型size用来记录队列的数据个数。
下面是队列结构的定义:

typedef struct Queue
{
	QNode* front;//指向队列头部的指针
	QNode* tail;//指向队列尾部的指针
	int size;//记录队列中元素个数
}Queue;

2 队列的初始化

刚开始队列为空,头指针front和尾指针tail指向NULL,此时队列中元素个数为0,因此将size初始化为0。
代码如下:

void QueueInit(Queue* pq)
{
	assert(pq);//检查参数有效性

	pq->front = pq->tail = NULL;
	pq->size = 0;
}

3 数据入队列

数据入队列分为一下两种情况:

  1. 队列为空时,新建节点,并用要入队列的数据初始化节点,此时front 和 tail都指向新插入的节点,同时将size+1。
  2. 队列不为空时,新建节点,并用要入队列的数据初始化节点,此时tail->next指向新插入的节点,更新tail指向新插入的节点。

数据1 2 3 4 入队列图解:
在这里插入图片描述
代码如下:

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);//检查参数有效性
	//创建新节点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush->malloc");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->val = x;
	//入队列
	//1. 队列为空
	//2. 队列不为空
	if (pq->front == NULL)
	{
		assert(!pq->tail);// 队列为空时,tail front都为空
		pq->front = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

4 数据出队列

我们知道,队列只能在队尾一端入数据,出数据时只能出队头的数据。因为它要保证有数据元素需要出队时,按照 “先进先出” 的原则。
数据出队的步骤如下:

  1. 在执行数据出队列操作之前,需要检查队列是否为空。如果队列为空(即没有数据),则无法执行出队列操作。
  2. 如果队列不为空,即存在数据,就可以执行出队列操作。
    此时数据出队列又分为两种情况:
    • 队列中只有一个数据:
      此时只需要将该数据所在节点释放,并将 front 和 tail 置为NULL即可。
    • 队列中有两个及以上数据:
      保存头节点下一个节点的地址,释放头节点,更新front,使front指向新的队头元素。

数据1 2 3 4 出队列图解:
在这里插入图片描述

代码如下:

void QueuePop(Queue* pq)
{
	assert(pq);//检查参数有效性
	assert(!QueueEmpty(pq));//检查队列是否为空,为空不能pop

	//出队列
	//1. 队列只有1个元素
	//2.队列有2个以上元素
	if (pq->front->next == NULL)
	{
		free(pq->front);
		pq->front = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->front->next;
		free(pq->front);
		pq->front = next;
	}
	pq->size--;
}

5 获取队头元素

获取队头元素的步骤如下:

  1. 在执行取队头元素操作之前,需要检查队列是否为空。如果队列为空(即没有数据),则无法执行此操作。
  2. 头指针front指向的就是队头元素,如要获取队头元素,因此只需返回front->val即可。

在这里插入图片描述代码如下:

QDataType QueueFront(Queue* pq)
{
	assert(pq);//检查参数有效性
	assert(!QueueEmpty(pq));//检查队列是否为空,为空不能取队头元素

	return pq->front->val;
}

6 获取队尾元素

获取队尾元素的步骤如下:

  1. 在执行取队尾元素操作之前,需要检查队列是否为空。如果队列为空(即没有数据),则无法执行此操作。
  2. 尾指针tail指向的就是队头元素,如要获取队尾元素,因此只需返回tail->val即可。

在这里插入图片描述
代码如下:

QDataType QueueBack(Queue* pq)
{
	assert(pq);//检查参数有效性
	assert(!QueueEmpty(pq));//检查队列是否为空,为空不能取队尾元素

	return pq->tail->val;
}

7 获取队列元素个数

队列中的size记录的就是队列中元素的个数,如要获取队列元素个数,返回size即可。
代码如下:

int QueueSize(Queue* pq)
{
	assert(pq);//检查参数有效性

	return pq->size;
}

8 判断队列是否为空

根据队列初始化函数,我们知道,队列为空时,front 和 tail 都指向NULL。
此时size=0,也可以用size来判断,这里作者选择用front 和 tail 来进行判断。
在这里插入图片描述
代码如下:

bool QueueEmpty(Queue* pq)
{
	assert(pq);//检查参数有效性
	return pq->front == NULL && pq->tail == NULL;
}

8 队列的销毁

链队列用来存储数据的节点都是动态申请的,因此队列销毁时,只需要遍历该链队列,依次释放每个节点。最后将 front 和 tail 置为NULL,size 置为0即可。
代码如下:

void QueueDestroy(Queue* pq)
{
	assert(pq);//检查参数有效性
	QNode* cur = pq->front;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->front = pq->tail = NULL;
	pq->size = 0;
}

至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。
创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !!!
在这里插入图片描述

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

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

相关文章

WorkPlus稳定服务助力行业千万用户,打造无界沟通协作平台

在企业移动数字化领域,WorkPlus以其十年如一日的研发实力和千万级用户案例,成为众多企业首选的移动数字化平台。究竟是什么样的力量支撑着WorkPlus在市场上占据如此重要的地位呢?接下来,让我们一起揭开WorkPlus的神秘面纱&#xf…

【开源】基于Vue.js的陕西非物质文化遗产网站

文末获取源码,项目编号: S 065 。 \color{red}{文末获取源码,项目编号:S065。} 文末获取源码,项目编号:S065。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 设计目标2.2 研究内容2.3 研究方法与…

网络唤醒原理浅析(Wake On LAN)

原理 将唤醒魔术包发送的被唤醒机器的网卡上,魔术包指AMD公司开发的唤醒数据包,具有远程唤醒的网卡都支持这个标准,用16进制表示如下: 6对“FF”前缀16次重复MAC地址,举个例子假如我的网卡MAC地址是:AA:BB:CC:DD:EE:…

现代 C++ 函数式编程指南

现代 C 函数式编程指南 什么是 柯里化 (Curry)什么是 部分应用 (Partial Application) 二元函数 (Partial Application)参数排序 (Partial Application) 应用场景 计算碳衰减周期求年…

Shell脚本:Linux Shell脚本学习指南(第二部分Shell编程)三

第二部分:Shell编程(三) 二十一、Shell declare和typeset命令:设置变量属性 declare 和 typeset 都是 Shell 内建命令,它们的用法相同,都用来设置变量的属性。不过 typeset 已经被弃用了,建议…

MySql之索引,视图,事务以及存储过程举例详解

一.数据准备 数据准备可参考下面的链接中的数据准备步骤 MySql之内连接,外连接,左连接,右连接以及子查询举例详解-CSDN博客 (如有问题可在评论区留言) 二.存储过程 1.定义 存储过程 PROCEDURE ,也翻译…

Leetcode—167.两数之和 II - 输入有序数组【中等】

2023每日刷题(四十一) Leetcode—167.两数之和 II - 输入有序数组 实现代码 /*** Note: The returned array must be malloced, assume caller calls free().*/ int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {*returnSiz…

过渡曲线的构造之平面PH曲线

平面PH曲线的构造及其相应性质 平面PH曲线的构造及其相应性质PH曲线理论三次PH曲线的构造及性质四次PH曲线的构造及性质五次PH曲线的构造及性质非尖点五次PH曲线尖点五次PH曲线 参考文献 平面PH曲线的构造及其相应性质 过渡曲线常需要满足在连接点处位置连续、曲率连续以及切线…

Docker Swarm总结+CI/CD Devops、gitlab、sonarqube以及harbor的安装集成配置(3/4)

博主介绍:Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 🍅文末获取源码下载地址🍅 👇🏻 精彩专栏推荐订阅👇🏻…

makefile编写练习

makefile编写练习 OVERVIEW makefile编写练习文件结构直接编译整个项目并运行将项目制作成为静态库将项目制作成为动态库 编写makefile文件来编译带头文件的程序, 文件结构 初始项目文件结构,如下所示: #ifndef ADD_HPP #define ADD_HPPint…

栈详解(C语言)

文章目录 写在前面1 栈的定义2 栈的初始化3 数据入栈4 数据出栈5 获取栈顶元素6 获取栈元素个数7 判断栈是否为空8 栈的销毁 写在前面 本片文章详细介绍了另外两种存储逻辑关系为 “一对一” 的数据结构——栈和队列中的栈,并使用C语言实现了数组栈。 栈C语言实现源…

Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线(实例分析)

Visual Studio 使用MFC 单文档工程从创建到实现绘制单一颜色直线和绘制渐变颜色的直线 本文主要从零开始创建一个MFC单文档工程然后逐步实现添加按键(事件响应函数),最后实现单一颜色直线的绘制与渐变色直线的绘制o( ̄▽&#xffe…

2、Burp使用

文章目录 一、为Firefox浏览器安装数字证书二、利用Intruder模块进行暴力破解 一、为Firefox浏览器安装数字证书 &#xff08;1&#xff09;利用Firefox浏览器访问http://burp或127.0.0.1:<监听端口>&#xff0c;点击页面右上侧的“CA Certificate”处下载CA证书&#xf…

靡靡之音 天籁之声 ——Adobe Audition

上一期讲到了和Pr配合使用的字幕插件Arctime Pro的相关介绍。相信还记得的小伙伴应该记得我还提到过一个软件叫做Au。 当人们对字幕需求的逐渐满足&#xff0c;我们便开始追求更高层次的享受&#xff0c;当视觉享受在进步&#xff0c;听觉享受想必也不能被落下&#xff01; Au即…

【模板】KMP算法笔记

练习链接&#xff1a;【模板】KMP - 洛谷 题目&#xff1a; 输入 ABABABC ABA 输出 1 3 0 0 1 思路&#xff1a; 根据题意&#xff0c;用到的是KMP算法&#xff0c;KMP算法思想是通过一个一个匹配首字母的原理进行整个匹配效果&#xff0c;当某个首字母不匹配的时候&#x…

【全栈开发】Blitz.js与RedwoodJS

技术的不断发展是必然的。如果你仔细观察这片土地&#xff0c;你会注意到随着技术的成熟而出现的某些模式。特别是&#xff0c;开发人员一直在努力提高性能&#xff0c;简化开发过程&#xff0c;增强开发人员体验。 在本指南中&#xff0c;我们将分析两个帮助全栈应用程序世界…

2023年3月电子学会青少年软件编程 Python编程等级考试一级真题解析(判断题)

2023年3月Python编程等级考试一级真题解析 判断题(共10题,每题2分,共20分) 26、在Python编程中,print的功能是将print()小括号的内容输出到控制台,比如:在Python Shell中输入print(北京,你好)指令,小括号内容可以输出到控制台 答案:错 考点分析:考查python中print…

Proteus仿真--基于PG12864LCD设计的指针式电子钟

本文介绍基于PG12864LCD设计的指针式电子钟&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真图如下 本设计中时间芯片选用DS1302芯片&#xff0c;液晶选用PG12864LCD模块&#xff0c;按键K1-K3&#xff0c;K1用于时分选择&#xff0c;K2用于调整功能&#xff0c…

积跬步至千里 || 为循环添加进度条

有时候&#xff0c;我们的Python程序需要运行较长时间&#xff0c;原因是一些环节占用时间太长&#xff08;如for循环&#xff09;。如果我们要观察那些占用时间任务的执行进度&#xff0c;那么有一个进度条能实时的显示任务进度情况的话&#xff0c;将会非常方便。而tqdm库就是…

Docker容器化部署若依微服务ruoyi-cloud项目

系统环境 接下来的内容以 Ubuntu 22.04.1 操作系统为例。 下载安装Docker Ubuntu hihi-IdeaCentre-GeekPro-15ICK:~$ sudo su [sudo] hi 的密码&#xff1a; roothi-IdeaCentre-GeekPro-15ICK:/home/hi# docker ps 找不到命令 “docker”&#xff0c;但可以通过以下软件包安…