深入了解队列:探索FIFO数据结构及队列

之前介绍了栈:探索栈数据结构:深入了解其实用与实现(c语言实现栈)

那就快马加鞭来进行队列内容的梳理。队列和栈有着截然不同的工作方式,队列遵循先进先出(FIFO)的原则,在许多场景下都表现出强大的效率和实用性

源码可以来我的github进行查找:Nerosts/just-a-try: 学习c语言的过程、真 (github.com)


文章目录


1.队列的概念及结构

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

入队列:进行插入操作 。此端称为队尾

出队列:进行删除操作 。此段称为队头

假设入队:A B C D

那么出队:A B C D


2.队列的实现

队列也可以数组和链表的结构实现,使用链表的结构来实现 更适合一些,因为使用数组的结构,出队列这个操作在数组头上出数据(届时会需要全体移动 ),效率会比较低

2.1项目文件规划

  • 头文件Queue.h:用来基础准备(常量定义,typedef),链表表的基本框架,函数的声明
  • 源文件Queue.c:用来各种功能函数的具体实现
  • 源文件test.c:用来测试功能是否有问题,进行基本功能的使用

2.2基本结构及各功能(Queue.h)

c 复制代码
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

typedef int QDataType;

typedef struct QueueNode//节点的结构体
{
	QDataType val;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size; //元素数量(空间换时间)
}Queue;

void QInit(Queue* q);//初始化
void QDestroy(Queue* q);//销毁

void QPush(Queue* q, QDataType x);//插入
void QPop(Queue* q);//删除

QDataType QBack(Queue* q);//返回最后一个节点数据
QDataType QFront(Queue* q);//返回第一个节点数据

bool QEmpty(Queue* q);//是否为空

int QSize(Queue* q);//元素数量

这两个结构体组合在一起,构成了队列数据结构的基本框架

  • QNode 结构体用于表示队列中的节点

  • Queue 结构体则用于管理整个队列的状态和属性

    这种设计使得队列的操作和功能得以清晰地表现和实现

2.3各功能具体实现(Queue.c)

初始化

c 复制代码
void QInit(Queue* q)
{
	assert(q);
	q->phead = q->ptail = NULL;
	q->size = 0;
}
  • 将队列的头尾指针设置为 NULL,表示队列为空。
  • 将队列中元素的数量设置为 0,因为队列此时没有任何元素

插入

c 复制代码
void QPush(Queue* q, QDataType x)
{
	assert(q);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	assert(newnode);//防止没有开辟成功(当人有点杞人忧天了)
	newnode->val = x;
	newnode->next = NULL;

	if (q->phead == NULL)
	{
		q->phead = q->ptail = newnode;
	}
	else
	{
		q->ptail->next = newnode;
		q->ptail = newnode;
	}
	q->size++;
}
  • 首先使用 assert 确保传入的队列指针 q 是有效的
  • 为新节点 newnode 分配内存,并设置其值为 xnext 指针指向 NULL
  • 如果队列为空(即头尾指针均为空),则将新节点同时设置为队列的头尾节点。
  • 如果队列不为空,则将新节点连接到队列尾部,并更新尾指针 ptail 指向新的尾节点。
  • 最后,增加队列的大小 size

删除

c 复制代码
void QPop(Queue* q)
{
	assert(q);
	assert(q->size > 0);
	QNode* next = q->phead->next;
	free(q->phead);
	q->phead = next;
	//当只有一个节点时:把	q->ptail = NULL;
	if (q->phead == NULL)
	{
		q->ptail = NULL;
	}
	q->size--;
}
  • 首先使用 assert 确保传入的队列指针 q 是有效的,并且队列中有元素即(size > 0
  • 通过 next 指针将队列头部的下一个节点保存下来,以备后续更新
  • 释放队列当前的头节点
  • 更新队列的头指针为下一个节点(如果有的话)
  • 如果删除节点后队列为空==(只有一个节点),则将尾指针 ptail 也设置为 NULL(一个节点时,二者指向同一个地址)==
  • 最后,减少队列的大小 size

返回最后一个节点数据

c 复制代码
QDataType QBack(Queue* q)
{
	assert(q);
	assert(q->ptail);
	return q->ptail->val;
}

返回第一个节点数据

c 复制代码
QDataType QFront(Queue* q)
{
	assert(q);
	assert(q->ptail);
	return q->phead->val;
}

是否为空

c 复制代码
bool QEmpty(Queue* q)
{
	assert(q);
	return q->size == 0;
}

节点数量

c 复制代码
int QSize(Queue* q)
{
	assert(q);
	return q->size;
}

销毁

c 复制代码
void QDestroy(Queue* q)
{
	QNode* cur = q->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	q->phead = q->ptail = NULL;
	q->size = 0;
}

队列的内容也整理完毕了,下一次会为大家带来二叉树和堆的相关内容,感谢大家的支持!!!

相关推荐
老鱼说AI9 小时前
算法基础教学第一步:数据结构
数据结构·python·算法
Yue丶越9 小时前
【C语言】自定义类型:联合体与枚举
c语言·开发语言
Bona Sun10 小时前
单片机手搓掌上游戏机(十五)—pico运行fc模拟器之编译环境
c语言·c++·单片机·游戏机
越努力越幸运50810 小时前
webpack的学习打包工具
前端·学习·webpack
white-persist10 小时前
【攻防世界】reverse | IgniteMe 详细题解 WP
c语言·汇编·数据结构·c++·python·算法·网络安全
韩曙亮10 小时前
【人工智能】AI 人工智能 技术 学习路径分析 ② ( 深度学习 -> 机器视觉 )
人工智能·深度学习·学习·ai·机器视觉
九千七52611 小时前
sklearn学习(3)数据降维
人工智能·python·学习·机器学习·sklearn
山峰哥11 小时前
沉浸式翻译插件深度评测:打破语言壁垒的黑科技利器
数据结构·科技·算法·编辑器·办公
写点什么呢12 小时前
使用PE安装Win10系统
学习