数据结构——队列(C语言版)

news2024/12/23 11:26:51

前言:

在学习完数据结构顺序表和链表之后,其实我们就可以做很多事情了,后面的栈和队列,其实就是对前面的顺序表和链表的灵活运用,今天我们就来学习一下队列的原理和应用。

准备工作:本人习惯将文件放在test.c、SeqList.c、SeqList.h三个文件中来实现,其中test.c用来放主函数,SeqList.c用来放调用的函数,SeqList.h用来放头文件和函数声明

目录

什么是队列?

队列的节点结构

队列的基本操作

1、初始化

2、销毁

3、增加(插入数据)

4、删除

5、取队头、取队尾、取长度、判断头指针是否为空

完整的队列实例

总结


什么是队列?

队列中的数据是按照先进先出的顺序的,也就是说先进去的数字也先出来

因为队列的这种性质,所以队列我们用链表来实现比顺序表方便很多,因为用顺序表每插入一个数或者删除一个数都需要遍历整个数组,这样就会很容易出错且不够方便,我们一般采用单链表来实现队列

队列的节点结构

队列采用的单链表的结构,所以与单链表差异不大

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

但是我们在操作中,因为队列是要先进先出,其实也就是尾部进数据,头部出数据,所以我们要定义一个头指针和一个尾指针指向头尾两个数据,这样有利于我们后面增加或者删除数据,我们可以再定义一个结构体来存放这两个指针

typedef struct Queue
{
	QNode* phead;    //头指针
	QNode* ptail;    //尾指针
	int size;        //队列中的元素个数
}Queue;

队列的基本操作

//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//增加
void QueuePush(Queue* pq,QDataType x);
//删除
void QueuePop(Queue* pq);
//取队头
QDataType QueueFront(Queue* pq);
//取队尾
QDataType QueueBack(Queue* pq);
//取长度
QDataType QueueSize(Queue* pq);
//判断是否为空
bool QueueEmpty(Queue* pq);

看上面的函数声明部分我们就可以看到我们每一步要实现的内容,接下来,我们就来一步一步进行实现

1、初始化

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

参数全是一个结构体指针,而且肯定不能为空,所以我们下面的函数基本都要对pq进行断言

2、销毁

将头指针指向的空间逐个释放,最后把头指针和尾指针均赋为空指

//销毁
void QueueDestroy(Queue* pq)
{
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

3、增加(插入数据)

因为先进先出,实际上数据就是从尾部插入,从头部出去,即插入形式为尾插

//插入
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	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++;
}

用单链表插入数据必须要考虑头部为空和不为空两种情况

4、删除

栈和队列都有一个特点就是,数据只会输出一遍,也就是数据一经输出就会销毁删除

如下:

1在输出之后就会被删除,删除的代码如下:

//删除
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	//1、一个节点
	//2、多个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* ptr = pq->phead->next;
		free(pq->phead);
		pq->phead = ptr;
	}
}

这里面又分为两种情况,难度不大,根据注释自行体会即可

5、取队头、取队尾、取长度、判断头指针是否为空

这几步难度不大,放在一起看看

取队头

//取队头
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
    
	return pq->phead->data;
}

取队尾

//取队尾
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->ptail->data;
}

取长度

//取长度
QDataType QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

判断头指针是否为空(这个函数应用上可以在下面的完整案列上体会一下)

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

完整的队列实例

test.c

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

SeqList.h

//队列
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

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

//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//增加
void QueuePush(Queue* pq,QDataType x);
//删除
void QueuePop(Queue* pq);
//取队头
QDataType QueueFront(Queue* pq);
//取队尾
QDataType QueueBack(Queue* pq);
//取长度
QDataType QueueSize(Queue* pq);
//判断是否为空
bool QueueEmpty(Queue* pq);

SeqList.c

//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//插入
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	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(!QueueEmpty(pq));

	//1、一个节点
	//2、多个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* ptr = pq->phead->next;
		free(pq->phead);
		pq->phead = ptr;
	}
}
//取队头
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
    
	return pq->phead->data;
}
//取队尾
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->ptail->data;
}
//取长度
QDataType QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

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

运行后结果:

总结

总之,其实队列就是对链表的应用,熟练栈和队列,对我们巩固顺序表和链表帮助很大,当然,队列在一些场景下很实用,后面我会出一个专门的习题讲解篇章,讲数据结构的一些经典题型,感兴趣的可以点赞关注一下

创作不易,还请各位大佬点赞支持一下!!!

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

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

相关文章

yolov5+pyside6+登录+用户管理目标检测可视化源码

一、软件简介 这是基于yolov5目标检测实现的源码,提供了用户登录功能界面; 用户需要输入正确的用户名和密码才可以登录。如果是超级管理员,可以修改普通用户的信息,并且在检测界面的右上角显示【管理用户】按钮。 支持图片、视频、…

RN封装的底部向上弹出的弹出层组件

组件代码 import React from react; import { View, StyleSheet, Modal, TouchableOpacity, Text, TouchableWithoutFeedback } from react-native;const BottomPopup ({ visible, onClose, children, leftButtonTitle, rightButtonTitle, onLeftButtonPress, onRightButtonP…

【前端】-【性能优化常识】

目录 前端性能优化指标首屏速度、白屏时间性能优化收效很大的操作:减少首屏资源体积收效不大或者特殊情况的优化操作 操作速度、渲染速度造成操作卡顿和渲染慢的场景性能优化 数据缓存 补充知识异步加载加载方式一:prefetch加载加载方式二:sc…

如何查询电脑是否被锁定了IP地址?锁定IP会出现什么问题?

前言 电脑刚到手的时候,基本上是通过路由器DHCP进行IP分配的。路由器DHCP分配IP给电脑的好处是网络不会出现IP冲突,网络能正常使用。 有些电脑可能在DHCP自动获取IP时出现错误,所以小伙伴就会通过手动设置IP让电脑可以正常上网。 这样的操…

[CISCN2019 华东北赛区]Web2

[CISCN2019 华东北赛区]Web2 随便注册一个登录,发现 还有反馈页面,一看就知道大概率是xss,应该是为了得到管理员cookie扫描了一下,果然有admin.php后台登录 buu可以连接访问外网了,所以内部的xss平台关闭了&#xff0…

【P1328】[NOIP2014 提高组] 生活大爆炸版石头剪刀布

[NOIP2014 提高组] 生活大爆炸版石头剪刀布 题目背景 NOIP2014 提高组 D1T1 题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种…

【笔记】OpenHarmony设备开发:搭建开发环境(Ubuntu 20.04,VirtualBox 7.0.14)

参考:搭建开发环境(HarmonyOS Device) Note:Windows系统虚拟机中Ubuntu系统安装完成后,根据指导完成Ubuntu20.04基础环境配置(HarmonyOS Connect 开发工具系列课) 系统要求 Windows系统要求&…

Warning logs 2024-03-23

给旧的笔记本安装ubuntu系统,并实现ssh远程连接 1、下载ubuntu系统 ubuntu下载链接 选择带桌面版本 2、准备U盘 3、使用UltraISO制作启动盘 使用UltraISO,打开刚才下载的ubuntu**.iso文件 4、进入BIOS,选择U盘启动 5、Warning 1 invali…

[Android]创建Google Play内购aab白包

开发时需要调试Google内购,需要先往Google商店传一个白包上去。确定包名,然后进行内购产品创建。 1.创建一个空项目,填写正式名称和正式包名。 如果你只是为一个测试开发账号打白包,然后进行内购测试,这时包名随便写…

深度学习中常用计算距离的几种算法对比与python实现

前言 距离度量在许多机器学习算法中扮演着至关重要的角色,无论是监督学习还是无监督学习。选择适当的距离度量可以显著影响模型的性能。 在高维数据集中,欧几里得距离可能会受到所谓的“维度诅咒”的影响,因为随着维度的增加,数…

如何打包springboot项目并部署服务器

创建一个springboot项目&#xff0c;先写一个接口&#xff0c;我这里是dabaimao/jiekou,启动访问 在pom中加上maven插件 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin<…

Qt 图形视图 /图形视图框架坐标系统的设计理念和使用方法

文章目录 概述Qt 坐标系统图形视图的渲染过程Item图形项坐标系Scene场景坐标系View视图坐标系map坐标映射场景坐标转项坐标视图坐标转图形项坐标图形项之间的坐标转换 其他 概述 The Graphics View Coordinate System 图形视图坐标系统是Qt图形视图框架的重要组成部分&#xf…

【win10 win11添加右键】git bash

打开注册表编辑器。 按下Win键 R&#xff0c;然后输入”regedit”并按下回车键来打开注册表编辑器。计算机\HKEY_CLASSES_ROOT\Directory\Background\shell\git_bash\command2. 导航到注册表路径&#xff1a;依次展开”HKEY_CLASSES_ROOT\Directory\Background\shell”。右键…

Git入门(Git快速下载,安装,配置,远程仓库,本地仓库,IDEA提交代码,VScode提交代码使用方案一体)

Git快速下载 通过阿里镜像可以自由挑选版本并快速下载CNPM Binaries Mirrorhttp://npm.taobao.org/mirrors/git-for-windows/ 这里安装最新版本 下载安装文件 安装完后双击文件即可开始安装git 安装 git的安装傻瓜式Next即可 配置 打开git&#xff1a;桌面空白处右击&#…

FTLK-1.3.9的编译和使用

文章目录 1. FTLK-1.3.9源码下载 1. FTLK-1.3.9源码下载 前往FTLK官网下载FTLK-1.3.9源码 *

ARM IHI0069F GIC architecture specification (4)

1.3 支持的配置和兼容性 在 Armv8-A 中&#xff0c;EL2 和 EL3 是可选的&#xff0c;PE 可以支持一个、两个或都不支持这些异常级别。 然而&#xff1a; • PE 要求EL3 支持安全和非安全状态。 • PE 需要EL2 来支持虚拟化。 • 如果未实施EL3&#xff0c;则只有一个安全状态。…

信号处理--基于DEAP数据集的情绪分类的典型深度学习模型构建

关于 本实验采用DEAP情绪数据集进行数据分类任务。使用了三种典型的深度学习网络&#xff1a;2D 卷积神经网络&#xff1b;1D卷积神经网络GRU&#xff1b; LSTM网络。 工具 数据集 DEAP数据 图片来源&#xff1a; DEAP: A Dataset for Emotion Analysis using Physiological…

【二】TensorFlow神经网络模型构建之卷积函数

卷积函数是构建神经网络的重要支架&#xff0c;是在一批图像上扫描的二维过滤器。 tf.nn.convolution(input,filter,padding,stridesNone,dilation_rateNone,nameNone,data_formatNone)该函数计算N维卷积的和。tf.nn.conv2d(input,filter,padding,strides,use_cudnn_on_gpuNon…

【卫星影像三维重建】有理函数模型库-rpcm

卫星成像模型rpcm库使用 1.介绍1.1 卫星成像模型1.2 rpcm库 2.安装2.1 依赖库2.2 安装 3.用法3.1 投影3.2 定位3.3 影像裁剪crop3.3.1 使用说明3.3.2 具体使用 3.4 footprint3.5 angle影像的成像夹角 4.参考 1.介绍 1.1 卫星成像模型 卫星遥感影像的成像模型是描述影像与地面…

从零开始搭建游戏服务器 第七节 创建GameServer

目录 前言正文创建GameServer模块修改配置创建NettyClient连接到登录服登录服修改创建协议游戏服注册到登录服 总结 前言 上一节我们使用自定义注解反射简化了协议解包和逻辑处理分发流程。 那么到了这里登录服登录服的架构已经搭建的差不多了&#xff0c;一些比较简单的、并发…