[数据结构 -- C语言] 队列(Queue)

news2024/11/21 7:40:14

目录

1、队列

1.1 队列的概念及结构

2、队列的实现

2.1 接口

3、接口的实现

3.1 初始化队列

3.2 队尾入队列

分析:

3.3 队头出队列

分析:

3.4 获取队列头部元素

3.5 获取队列尾部元素

3.6 获取队列中有效元素个数

3.7 检测队列是否为空

3.7.1 int 类型判空

3.7.2 bool 类型判空

3.8 销毁队列

4、完整代码

5、效果展示


1、队列

1.1 队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

2、队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数
组头上出数据,效率会比较低。本篇文章就是用链表实现队列。

2.1 接口

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// 链式结构:表示队列 
typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* front;
	QNode* rear;
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

3、接口的实现

3.1 初始化队列

我们将队头指针与队尾指针都置为 NULL,并将队列的大小赋值为 0。

void QueueInit(Queue* q)
{
	assert(q);

	q->front = NULL;
	q->rear = NULL;	
	q->size = 0;
}

3.2 队尾入队列

void QueuePush(Queue* q, QDataType data)
{
	assert(q);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail:");
		return;
	}
	newnode->data = data;
	newnode->next = NULL;

	if (q->rear == NULL)
	{
		assert(q->front == NULL);

		q->front = q->rear = newnode;
	}
	else
	{
		q->rear->next = newnode;
		q->rear = newnode;
	}
	q->size++;
}

分析:

我们是以链表实现队列的,所以每次入队的时候我们都要 malloc 一个 newnode 结点出来,将 newnode->data = data,newnode->next = NULL。

下来就是连接了:

我们要考虑这个结点是否是队列的第一个结点。

1、是队列的第一个结点的话,我们让头尾指针都指向这个结点(q->front = q->rear = newnode);

2、不是队列的第一个结点,我们将尾指针的next赋值为新节点(q->rear->next = newnode;), 再让尾指针指向新节点( q->rear = newnode;);

3、让队列的 size++。

3.3 队头出队列

void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	//1.一个结点
	if (q->front->next == NULL)
	{
		free(q->front);
		q->front = q->rear = NULL;
	}
	else//2.多个结点
	{
		QNode* next = q->front->next;
		free(q->front);
		q->front = next;
	}
	q->size--;
}

分析:

出队的时候要考虑队列是否是一个结点:

1、队列中只有一个结点,我们将这一个结点释放掉后(free(q->front)),将头、尾指针都置空(q->front = q->rear = NULL);

2、队列中有多个结点,那我们就将队头的下一个结点先保存起来(next = q->front->next),然后将队头释放掉(free(q->front)),最后让队头指向释放前队头的下一个结点(q->front = next);

3、最后让队列的 size--。

3.4 获取队列头部元素

取队头元素时,我们先要对队列进行判空,如果队列为空,那就不存在队头元素。

QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	return q->front->data;
}

3.5 获取队列尾部元素

取队尾元素时,我们先要对队列进行判空,如果队列为空,那就不存在队尾元素。

QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	return q->rear->data;
}

3.6 获取队列中有效元素个数

我们在创建队列的结构体时,在里面创建了一个变量 size,它专门记录队列中的元素个数,所以在这我们只要返回 q->size就可以了。如果没有定义 size 变量的话,我们遍历一遍队列,用计数器来统计一下个数也是可以的。

int QueueSize(Queue* q)
{
	assert(q);

	return q->size;
}

3.7 检测队列是否为空

3.7.1 int 类型接口

这里我们约定,为空返回非 0,非空返回 0。

int QueueEmpty(Queue* q)
{
	assert(q);

	if (0 == q->size)
		return 1;
	else
		return 0;
}

3.7.2 bool 类型接口

直接判断队头是否为空,队头为空队列就是空。

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

	return q->front == NULL;
}

3.8 销毁队列

销毁我们已经写的很多了,这就直接拿捏。我们先将单链表进行释放,这里有一个注意点,我们要先记下下一个位置,然后释放当前位置,然后将下个位置再交给当前位置来迭代。最后将头、尾指针置空,再将 size 置0。

void QueueDestroy(Queue* q)
{
	assert(q);

	QNode* cur = q->front;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	q->front = q->rear = NULL;
	q->size = 0;
}

4、完整代码

完整代码在代码仓库,入口:C语言: C语言学习的代码,多复习 - Gitee.com

5、效果展示

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

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

相关文章

要想抢到演出票,总共分几步?

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 小黑 编辑 / SandLiu 卷圈 监制 / 姝琦 文案 / 小黑 产品统筹 / bobo 录音支持 / 声湃轩天津录音间 报复性听歌正席卷多地&#xff0c;一路狂飙的演唱会市场背后&#xff0c;是一票难求、与黄牛斗智斗勇的粉丝们。 是…

GPT专业应用:自动撰写宣传稿

●图片由Lexica 生成&#xff0c;输入&#xff1a;Staff working on product promotion 宣传稿是指按照有关政策文件或相关精神&#xff0c;以宣传某种主张、某项工作、某件事情等为目的&#xff0c;为获得理解、支持而撰写的应用文。基本格式包含四个要素&#xff0c;分别是标…

chatgpt赋能Python-numpy如何下载

如何下载Numpy 对于python编程者&#xff0c;numpy是不可或缺的一个库。它提供了一种操作向量、矩阵、数组的方式&#xff0c;使得我们能够高效地进行数据处理和科学计算&#xff0c;甚至还能进行线性代数运算和傅里叶变换等高级操作。 那么&#xff0c;在这篇文章中&#xf…

第十七章 使用PXE+Kickstart无人值守安装服务

文章目录 第十七章 使用PXEKickstart无人值守安装服务一、无人值守系统1、无人值守安装系统的工作流程2、PXE介绍 二、部署相关服务程序1、临时关闭防火墙2、配置DHCP服务程序&#xff08;1&#xff09;、安装dhcp服务程序&#xff08;2&#xff09;、编辑配置文件&#xff08;…

为什么需要代理ip

使用代理IP的情况不限于某一特定行业&#xff0c;因为在不同行业中都可能需要根据不同需求和目的来使用代理IP。以下是一些行业中常见需要使用代理IP的情形&#xff1a; 1、爬虫行业 对于需要爬取网站数据的用户&#xff0c;使用代理IP可以帮助隐藏真实IP地址及请求头信息&am…

Flowable 生成的表都是干嘛的?(二)

一.简介 Flowable 默认一共生成了 79 张数据表&#xff0c;了解这些数据表&#xff0c;有助于我们更好的理解 Flowable 中的各种 API。 接下来我们就对这 79 张表进行一个简单的分类整理。 ACT_APP_*&#xff08;5&#xff09;ACT_CMMN_*&#xff08;12&#xff09;ACT_CO_*…

Linux之后台终端

1、后台终端 当我们连接一个终端并执行一个程序时&#xff0c;关闭终端时程序也被终结。比如想在终端中执行一个web服务器&#xff0c;想一直后台运行&#xff0c;可以使用screen这个工具 2、screen工具 screen工具不是自带的所以需要sudo apt update && sudo apt i…

excel 甘特图制作(详细)

文章目录 前言excel 甘特图制作(详细)1. 模板字段确认2. 冻结至F列3. 在第二行确认状态颜色4. 设置开始日期5. 先将第3行居中&#xff0c;然后状态那列设置下拉6. 填充任务7. 开启日期与结束日期设置单元格式为日期8. 填充任务9. 制作日期10. 制作日期交互11. 修改开始时间范围…

数说故事与华为云签署全面合作协议,共同升级数字世界营销新体验

5月16日&#xff0c;由广东省工业和信息化厅、广州市人民政府联合指导&#xff0c;华为主办的2023华为云城市峰会首站登录广州。为贯彻落实广东省高质量发展大会的工作要求&#xff0c;响应《广东省制造业高质量发展“十四五”规划》, 本次大会围绕“在工业 为工业”主题并邀请…

普通表转分区表

当一张表数据过大时&#xff0c;可以进行垂直拆分&#xff08;每张表存储部分字段&#xff09;和水平拆分&#xff08;每张表字段完整&#xff0c;数据只存储一部分&#xff09; 这里记录的是水平拆分 首先对数据进行备份 create table 备份表名 as (select * from 原表名);…

Vue 3 第二十章:组件八(组件高级特性-组件的全局注册和局部注册)

文章目录 1. 全局注册组件2. 局部注册组件 Vue3 允许我们在全局注册组件&#xff0c;这使得我们可以构建更加灵活和可扩展的应用程序。同时&#xff0c;局部注册可以帮助我们更好地组织代码并提高应用程序的性能。 1. 全局注册组件 通过 app.component 方法可以在 Vue3 中创建…

钓鱼对抗之 Coremail安全拦截

作者简介&#xff1a; 胡晓磊&#xff0c;男&#xff0c;山东省城市商业银行合作联盟有限公司邮箱管理员&#xff0c;Coremail管理员社区特邀大咖 钓鱼邮件&#xff0c;是一种常见的网络诈骗手段。一般目的是用来欺骗收件人&#xff0c;将账号、口令或密码等信息回复给指定的接…

(数字图像处理MATLAB+Python)第八章图像复原-第五、六节:盲去卷积复原和几何失真校正

文章目录 一&#xff1a;盲去卷积复原&#xff08;1&#xff09;概述&#xff08;2&#xff09;程序 二&#xff1a;几何失真校正&#xff08;1&#xff09;概述&#xff08;2&#xff09;程序 一&#xff1a;盲去卷积复原 &#xff08;1&#xff09;概述 盲去卷积复原&#…

Java中的ORM框架有哪些,Hibernate 使用讲解

简介 在Java开发中&#xff0c;使用ORM框架是一种常见的开发方式。ORM&#xff08;Object-Relational Mapping&#xff09;框架是一种将对象模型和关系模型进行映射的技术&#xff0c;它使得Java开发人员可以使用面向对象的方式来操作关系型数据库&#xff0c;而无需直接使用S…

拍卖行搜索包分析

《天涯明月刀》的明文包内容大多比较简单&#xff0c;不过也有个别封包的结构较大&#xff0c;分析起来较为复杂&#xff0c;以拍卖行的搜索函数为例。 首先通过send返回到明文包的位置(如图) 这个封包的大小为0x56&#xff0c;随意搜索一个物品的名字使游戏断下(如图) 在这…

Vue 3 脚手架搭建

Vue 3 脚手架搭建 一、环境准备1.1 node.js 安装1.2 包管理工具安装&#xff1a;可选 二、创建项目2.1 使用 npm2.2 使用 yarn 三、配置项目3.1 安装初始依赖3.2 增加依赖3.2 配置自动导包3.3 配置 eslint 规则3.4 .vue 文件导入报错解决 四、路由配置4.1 路由类型定义4.2 inde…

加密解密软件VMProtect入门使用教程(八)控制台版本

VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic&#xff08;本机&#xff09;、Virtual Pascal和XCode编译器。 同时&#xff0c;VMProtect有一个内置的反汇编程序&#xff0c;可以与Windows和Mac OS X可执行文件一起…

【C++初阶】模板

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;C初阶 ⭐代码仓库&#xff1a;C初阶 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们的支持是我…

Java应用程序性能调优的秘诀:掌握JVM自带的命令行工具

Java 自带了多个 JVM 调优工具&#xff0c;以下是其中一些常用的工具&#xff1a; 1&#xff09;jps&#xff08;JVM Process Status Tool&#xff09;&#xff1a; 用于显示当前系统中所有正在运行的 Java 进程的 PID 和相关信息。 2&#xff09;jstat&#xff08;JVM Stati…

常用的表格检测识别方法-表格区域检测方法(上)

常用的表格检测识别方法 表格检测识别一般分为三个子任务&#xff1a;表格区域检测、表格结构识别和表格内容识别。本章将围绕这三个表格识别子任务&#xff0c;从传统方法、深度学习方法等方面&#xff0c;综述该领域国内国外的发展历史和最新进展&#xff0c;并提供几个先进…