c语言----队列

news2024/11/20 9:43:29

        很久没有写文章了。因为放假了嘛,给自己稍微放松了一下,所以最近的更新很慢。呜呜下一次一定改。然后咧。今天我想与大家分享的是队列。虽然这个知识点我们应该在讲了堆的实现就应该写的,但是后面忘了,以为自己是写了的。但是昨天看了看自己写的目录才发现自己忘了写队列了。所以今天把队列补上,并且当我们写了队列后我们会写队列与堆的相互实现。

队列的含义

        大家如果一直有在看我的文章的话可能已经了解了队列的含义了,但按照规矩我还是向大家解释一下队列的含义。队列咧。就像我们排队买奶茶一样。先进行排队的人可以先买后进行排队的人后买,我们大家都遵守的规则,然后队列也遵守这个规则。就好比我们的堆是后进先出一样。队列必须遵守这个。还有就是队列他只能头删和尾插。当然还有一些其他的基本上做比如说什么判空或者返回头元素之类的。那么接下里我们就来康康实现队列需要怎么搞。

实现队列

     创建结构体

       我们都说了,队列与堆可以相互出现,其实就代表他们的大体结构是差不多的。就只需要注意一下他们的定义的区别就可以了。那么我们应该也会要像他们一样先创建一个结构体来储存数据。但是我们创建结构体又不能指向开始一样只创建一个结构体。因为如果我们只创建一个结构体的话,我们需要数据节点为头节点,还需要再一个数组的个数还需要一个尾节点。然后还有指向的一个数据。如果都放在一个这个里面的话会比较麻烦,但是我们可以将头节点和尾节点直接单独拎出来。但是我们创建的结构里面的数据还是以最开始的节点为基准。大家可以先看一下我的代码是怎么样的:

typedef int QDateType;//队列存储数据类型

typedef struct QueueNode //队列元素节点
{
	QDateType val;//队列的元素个数
	struct QueueNode* next;//指向的下一个节点
}QueueNode;

typedef	struct Queue //队列
{
	QueueNode* head;//头节点
	QueueNode* tail;//尾节点
}Queue;

5c9d1e95af7d4a5f9884c89ba6e34443.png

        大家可以稍微看一下,我这个可能会比较抽象,但确实就像这样子。就好像创建了一个结构体,然后在他结构体里面再分化一下。 

队列的初始化

       对于队列的初始化,这样就很是很简单的,因为我们只需要将它的头节点和尾节点置为空就可以了。

void QueueInti(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}
队列的销毁

       相较于队列的初始化,队列的销毁就相对会麻烦一点。因为我们首先需要判断是否为空指针。然后再创建一个指针为头指针,依次销毁置空。然后再将头尾节点置为空就结束了。虽然也是很简单的,但是相较于初始化确实多了几行代码。

void QueueDestory(Queue* pq)
{
	assert(pq); //防止pq为空指针
	QueueNode* cur = pq->head;//创建一个零时节点以免对代码实现干扰
	while (cur)
	{//依次销毁,并且换到下一个
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->tail = pq->head = NULL;//头尾置为空
}
队列的入队列 

      我们在前面说我们队列是先进先出的,那么入队列肯定也是依次从头节点开始进入。所以我们对入队列就是需要开辟一个新的节点来存储数据。然后将他放在尾节点的后面然后将尾节点移位,那么这个头插就结束了。但是我们还需要思考的是并不是我们每一次使用开始队列就有数据了。那我们是不是需要区分一下,如果对于你开始里面没有数据应该怎么处理?就是当头节点和尾节点都是同一个的时候,还没有数据的时候。那么我们是不是应该让头节点和尾节点的同时置于相同的数据。因为这个时候我们头和尾节点是相同的呀。所以这也是我们需要考虑的一点。

void QueuePush(Queue* pq, QDateType x)
{
	assert(pq); //防止pq为空指针

	QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));//创建新节点存放数据
	if (NULL == newNode)//判断是否创建好了
	{
		printf("malloc error\n");
		exit(-1);
	}
	newNode->val = x;
	newNode->next = NULL;//开辟一个新节点存储数据

	if (pq->tail == NULL)//判断是否为空队列
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newNode;
	}
	else
	{
		pq->tail->next = newNode;
		pq->tail = newNode;
	}
}
队列的出队列

       我们在前面实现了尾插后,接下来就应该实现头删了。既然是头删,那么我们是不是要思考一下。假如只有一个指针的话,就是例如我刚插入一个之后,我就立马删除了。已经有很多个元素了,我再删除这两种区别。所以我们就需要分别的对待这两件事情。大家想一想,如果只有一个指针的话,我们是不是只需要将头和尾直接置为空就可以了?因为只有一个节点嘛,然后我删除一个节点,那是不是周围空了?所以就只需要将头和尾置空一下就好了。然后还有就是正常情况下,我们不能直接将头删掉,如果删掉的话是不是就不能找到下一个节点了?所以我们正常的情况下需要创建一个临时节点,然后再来删除。

void QueuePop(Queue* pq)
{
	assert(pq);//防止pq为空指针
	assert(pq->head && pq->tail); //防止队列为空队列
	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;
	}
}
队列的头元素

        对于队列的取头元素这是比较简单的,因为我们在最开始创建的时候就已经写了一个头节点和尾节点了。只需要判断节点是否为空就可以了。

QDateType QueueFront(Queue* pq)
{
	assert(pq);//防止pq为空指针
	assert(pq->head && pq->tail); //防止队列为空队列

	return pq->head->val;
}
   队列的判空

       关于队列的判空呢其实也是比较简单的。如果当头节点和尾节点相同,并且为都为空的话,那么肯定就是空的队列了。当然我们还是需要判断指针是否为空。

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL;
}
队列的元素个数

         对于判断队列的元素个数,我的这个方法其实是比较麻烦的,我是像在需要队列个数的时候重新执行一遍便利的过程,这样我们就可以得出元素的个数了。但是也可以在创建结构体的那个地方再加一个size反正就是一个计数的就可以了,那么如果当我们计数的为零,那么就说明是队列为空,并且对于我们计算元素个数也是很方便的,当然这也是另外一种的方法,我这里就先写我原本的遍历一遍就好了,大家如果感兴趣的话,后面可以尝试一下。

int QueueSize(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;//创建一个临时节点,更加方便操作
	int count = 0;
	while (cur)
	{
		cur = cur->next;
		count++;
	}
	return count;//返回个数
}

总结

       好了,上面就是关于队列的大部分使用方法了。当然还有很多对于这个的延伸,这就可能会用在后面的题目上。后面的面试题之类的。那可以多尝试一下练题,然后就能加深一下对队列的一些的相关知识的巩固。那么接下来来我就这样所有的代码给大家看一下。

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

typedef int QDateType;

typedef struct QueueNode
{
	QDateType val;
	struct QueueNode* next;
}QueueNode;

typedef	struct Queue
{
	QueueNode* head;
	QueueNode* tail;
}Queue;

void QueueInti(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->tail = pq->head = NULL;
}

void QueuePush(Queue* pq, QDateType x)
{
	assert(pq);

	QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (NULL == newNode)
	{
		printf("malloc error\n");
		exit(-1);
	}
	newNode->val = x;
	newNode->next = NULL;

	if (pq->tail == NULL)
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newNode;
	}
	else
	{
		pq->tail->next = newNode;
		pq->tail = newNode;
	}

}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head && pq->tail);
	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;
	}
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL;
}

QDateType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->val;
}

int QueueSize(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	int count = 0;
	while (cur)
	{
		cur = cur->next;
		count++;
	}
	return count;
}

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

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

相关文章

SQL二次注入原理分析

二次注入在测试的时候比较少见&#xff0c;或者说很难被测出来&#xff0c;因为测的时候首先要去找注入的位置&#xff0c;其次是去判断第一次执行的SQL语句&#xff0c;然后还要去判断第二次进行调用的 SQL 语句。而关键问题就出在第二次的调用上面。 下面以一个常用过滤方法…

STM32学习历程(day2)

GPIO解释 GPIO(General-purpose input/output) 可以配置为八种输入输出模式 引脚电平 0V-3.3V 部分引脚可容忍5v 输出模式可控制端口输出高低电平 用以驱动LED、控制蜂鸣器、模拟通信协议输出时序 输入模式可读取端口的高低电平或电压&#xff0c;用于读取按键输入、外界…

网络IO模型之多路复用器.md

多路复用是什么&#xff1f;怎么理解&#xff1f; 本文主要涉及为 程序中处理网络IO时的模型&#xff0c;对于系统内核而言网络IO模型。这里只做普及使用 前置知识&#xff0c;什么是IO&#xff1f;怎么理解IO IO其实就是In和Out。中文翻译是输入和输出&#xff0c;只要涉及到输…

js 递归调用 相同对象--数组递归调用

<div class="save-cl"> <a-button @click="saveCl" >保存为常用策略</a-button> </div> saveCl(){ console.log(this.form.filterList[0],--------常用策略)// 此对象为上图对象 console.log(this.allElementsHaveValue(thi…

【BUUCTF-PWN】7-[第五空间2019 决赛]PWN5

参考&#xff1a;BUU pwn [第五空间2019 决赛]PWN5 //格式化字符串漏洞 - Nemuzuki - 博客园 (cnblogs.com) 格式化字符串漏洞原理详解_printf 任意内存读取-CSDN博客 32位小端排序&#xff0c;有栈溢出保护 运行效果&#xff1a; 查看main函数 存在格式化字符串漏洞 输…

Ubuntu 22.04.4 LTS 安装配置 MySQL Community Server 8.0.37 LTS

1 安装mysql-server sudo apt update sudo apt-get install mysql-server 2 启动mysql服务 sudo systemctl restart mysql.service sudo systemctl enable mysql.service #查看服务 sudo systemctl status mysql.service 3 修改mysql root密码 #默认密码为空 sudo mysql …

数据结构(3.8)——栈的应用

栈在括号匹配中的应用 流程图 代码 #include <stdio.h> #include <stdlib.h> #define MaxSize 10typedef struct {char data[MaxSize];int top; } SqStack;// 初始化栈 void InitStack(SqStack* S) {S->top -1; // 初始化栈顶指针 }// 判空 bool StackEmpty(…

在线签约如何选择?2024年10款顶级app大比拼

支持电子合同签约的10大app&#xff1a;e签宝、上上签、DocuSign、契约锁、Adobe Sign、法大大、SignNow、安心签、HelloSign、PandaDoc。 无论是企业之间的交易还是个人服务合同&#xff0c;线上电子合同签约提供了一种便捷、高效且安全的方式来处理法律文档。本文将介绍几款优…

什么是YUV和IPB,PTS和DTS,视频编码解码过程

YUV 是一种在视频处理和压缩中常用的颜色空间。 它将图像的亮度 (Y) 与色度 (U 和 V) 成分分开。 这种分离对视频压缩和广播非常有益&#xff0c; 因为人眼对亮度变化比对颜色变化更敏感。 YUV 组件简介 Y (亮度)&#xff1a;表示图像的亮度或灰度信息。U (色度)&#xff1a;…

泛微开发修炼之旅--29用计划任务定时发送邮件提醒

文章链接&#xff1a;29用计划任务定时发送邮件提醒

华为云交付模式和技术支持

华为云交付模式概览 用户由于自身或者企业属性的原因&#xff0c;对于使用云服务的要求也会有所不同。因此&#xff0c;华为云针对于不同用户的不同要求&#xff0c;提供了以下三种交付模式供用户选择。 公有云模式 公有云的核心属性是共享资源服务华为公有云为个人和企业用户…

人工智能对网络安全有何影响?

人工智能网络安全在短期、中期和长期如何变化 当今数字时代网络安全的重要性 在谈论人工智能在网络安全中的作用时&#xff0c;必须首先考虑短期影响&#xff0c;因为它们是最明显的&#xff0c;而且它是一个未知的领域&#xff0c;需要超越直接炒作的能力。 因此&#xff0…

免费办公软件 -- LibreOffice v24.2.4

软件简介 LibreOffice是一款免费且开源的办公软件套件&#xff0c;它为个人和商业用户提供了一套完整的工具&#xff0c;用于处理文本文档、电子表格、演示文稿和其他类型的文件。这款软件兼容 Microsoft Office 的文件格式&#xff0c;如 .docx、.xlsx 和 .pptx&#xff0c;使…

go语言day08 泛型 自定义错误处理 go关键字:协程

泛型&#xff1a; 抛错误异常 实现error接口类型 用java语言解释的话&#xff0c;实现类需要重写error类型的抽象方法Error().这样就可以自定义异常处理。 回到go语言&#xff0c;在Error()方法中用*argError 这样一个指针类来充当error接口的实现类。 在f2()方法中定义返回值…

等保2.0标准相比之前的有哪些重大变化?

在数字化的浪潮中&#xff0c;网络安全如同一艘坚固的航船&#xff0c;承载着国家与民族的希望&#xff0c;驶向信息化的彼岸。等级保护制度&#xff08;等保&#xff09;作为中国网络安全的守护神&#xff0c;经过岁月的洗礼与智慧的积淀&#xff0c;迎来了等保2.0的时代&…

【Python】已解决:NameError: name ‘reload’ is not defined

文章目录 二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;NameError: name ‘reload’ is not defined 一、分析问题背景 在使用Python进行开发时&#xff0c;有时我们可能需要重新加载某个已经导入的模块&#xff0c;以便应用模块中的最…

CTFHUB-SSRF-数字IP Bypass

开启题目&#xff0c;页面空白 根据提示&#xff0c;不能使用点分十进制&#xff0c;尝试将127.0.0.1转换为十六进制形式&#xff0c;也就是0x7f000001 构造题目有所需 Payload ?url0x7f000001/flag.php 访问得到了flag 八进制&#xff1a;0177.000.000.001 十进制&#xf…

技术赋能政务服务:VR导视与AI客服在政务大厅的创新应用

在数字化转型的浪潮中&#xff0c;政务大厅作为服务民众的前沿阵地&#xff0c;其服务效率和质量直接影响着政府形象和民众满意度。然而&#xff0c;许多政务大厅仍面临着缺乏智能化导航系统的挑战&#xff0c;这不仅增加了群众的办事难度&#xff0c;也降低了服务效率。维小帮…

MySQL逻辑备份恢复实战之mysqldump与mysqlpump

MySQL逻辑备份介绍 逻辑备份&#xff1a; 备份内容&#xff1a;数据库的结构定义语句数据内容的插入语句&#xff0c;备份出来的文件是可以编辑的。 适用场景&#xff1a;数据量少的数据库&#xff0c;比较适合100G数据量以内的。 逻辑备份的特点&#xff1a; sql语句组成的…

Vue3进度条nprogress(手机端、PC端通用)

Vue3进度条nprogress是一个用于显示页面加载进度的库。要在Vue3项目中使用nprogress&#xff0c;需要先安装它&#xff0c;然后在你的项目中引入和使用。 安装nprogress npm install nprogress --save配置nprogress 在目录src下创建nprogress文件夹&#xff0c;里面创建nprogr…