C语言队列的含义与队列数据操作代码详解!

引言:于本篇博客当中,我们将讲到数据结构——队列的有关知识。而对于这次的队列,我们将会在单链表的基础上实现。

更多有关C语言和数据结构知识详解可前往个人主页:计信猫

一,队列的含义

        队列是一种特殊的线性表,它只允许在表的一端进行插入数据的操作,另一端进行删除数据的操作

队头:进行数据删除的一端

队尾:进行数据插入的一端

        所以,队列便可以用如下的图进行表示:

         而正因为队列遵循FIFO原则(即先进先出),使得入队列出队列的顺序一一对应,也就多被应用于广度优先遍历的操作。

二,队列结构体的定义

        老样子,我们仍然使用三文件操作法,分别创建Queue.h、Queue.c、test.c三个文件。

        因为先前提到,队列会在单链表的基础上实现,那么我们就需要先定义一个单链表结构体

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

        但是,因为在队列之中,我们只需要关注队列队头队尾的两个节点即可,并且为了避免二级指针的使用难以理解,所以我们选择再定义一个结构体Queue用于储存队列队头队尾两节点

typedef struct Queue
{QNode* phead;QNode* ptail;int size;//记录队列中的节点个数
}Queue;

        包含可能用到的头文件后,我们的Queue.h的代码内容如下:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;
typedef struct Queue
{QNode* phead;QNode* ptail;int size;//记录队列中的节点个数
}Queue;

三,队列数据操作函数

1,队列的初始化

        队列的初始化其他数据结构的初始化别无它异,我们只需要将结构体中的指针类型初始化为NULL整型类型初始化为0就可以了。直接上代码:   

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

2,队列的尾插

        对于队列的尾插,其实也就和单链表的尾插一模一样。我们只需要使用malloc函数申请一个节点的空间,然后将新创建的节点连在队列的尾部,同时将ptail指针移到新形成的队尾,最后的最后,一定不要忘记size++。这样,一个队列的尾插函数就成功写出了。

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));//创建新节点if (newnode == NULL){perror("malloc fail!");return;}newnode->next = NULL;newnode->val = data;//队列元素为0个时if (q->ptail == NULL){q->phead = q->ptail = newnode;}//队列有元素时else{q->ptail->next = newnode;q->ptail = newnode;}q->size++;
}

3,队列的头删

        因为队列只可以在队头进行数据删除,所以队列就只有一个头删函数

        如上图所示,对于队列的头删函数,我们需要首先创建节点结构体指针next记录队头的下一个节点的地址,以免队头free掉之后导致的后续节点的丢失,然后我们再将phead指针赋值为next,最后再进行size--即可

        但是有一个特殊情况,当队列只有一个节点的时候,我们进行队列的头删之后,ptail则会变成野指针,这时候我们就需要特殊处理,将ptail也赋值为NULL,防止野指针的出现。如图:

         综上所述,我们的队列头删函数如下: 

// 队头出队列 
void QueuePop(Queue* q)
{assert(q);assert(q->size > 0);QNode* next = q->phead->next;free(q->phead);q->phead = next;//特殊情况:队列只有一个节点的时候if (q->phead == NULL){q->ptail = NULL;}//勿忘size--q->size--;
}

4,获取队列头部数据

        这时候,我们所创建的Queue结构体就派上大用场了,因为这个结构体直接就保存了我们的phead节点,所以我们直接使用就可以了。代码如下:

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{assert(q);assert(q->phead);return q->phead->val;
}

5,获取队列尾部数据 

        那么这个函数,也就跟前一个函数相差不大了。都是直接使用Queue结构体就可以了,我们直接上代码:

// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{assert(q);assert(q->ptail);return q->ptail->val;
}

6,获取队列有效元素个数 

        在Queue结构体中,我们早就使用了size来记录有效元素的个数,所以我们直接返回size的值即可。

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(q);return q->size;
}

7,判断队列是否为空 

        该函数的返回值为布尔类型,即truefalse

队列为空,返回:true

队列不为空,返回:false

        对于队列是否为空,我们只需要判断size是否为零就可以了。所以代码如下:

// 检测队列是否为空
bool QueueEmpty(Queue* q)
{assert(q);return q->size == 0;//若size等于零,则表达式为真,则队列为空//若size不等于零,则表达式为假,则队列为假
}

8,队列的销毁 

         因为我们创建队列时使用了malloc函数,故为了防止内存溢出,我们需要创建一个队列的销毁函数,来完成释放队列申请的空间的操作。

        在该函数中,我们需要再创建一个QNode结构体指针cur用于保存即将被释放的节点的下一个节点的地址,以防止地址的丢失,然后再使用free函数释放掉节点即可。最后的最后,勿忘将size置为零

        所以我们的代码如下:

// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);QNode* next = q->phead;while (next){QNode* cur = next->next;free(next);cur = next;}q->size = 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8 Tensorrt Python/C++部署详解

按照大佬的方法进行部署&#xff0c;但是中间出现了很多问题&#xff0c;这里进行一下总结。 YOLOv8 Tensorrt Python/C部署教程_yolo 安装tensorrt-CSDN博客https://blog.csdn.net/weixin_45747759/article/details/130341118 Monday-Leo/Yolov5_Tensorrt_Win10: A simple i…

上线了《學點笔录》,更方便翻阅笔录

大家好&#xff0c;我是学点&#xff0c;整理了一下自己笔记、摘要、记录《學點笔录》并且上线了为更方便翻阅 https://code.yellowcan.cn 欢迎来我的學點笔录网站&#xff01;笔录会关于与编程有关&#xff0c;比如bug记录、bug解决过程、编程笔记等等&#xff0c;帮助回忆阅…

【前端热门框架【vue框架】】——对组件进行更加简洁合理的处理和解释(一)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;程序员-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

八、VUE内置指令

一、初识VUE 二、再识VUE-MVVM 三、VUE数据代理 四、VUE事件处理 五、VUE计算属性 六、Vue监视属性 七、VUE过滤器 七、VUE内置指令 九、VUE组件 v-text 向其所在的节点中渲染文本内容。 (纯文本渲染)与插值语法的区别&#xff1a;v-text会替换掉节点中的内容&#xff0c;{{x…

HashMap前世今生

概述 HashMap是我们常用的一种数据结构&#xff0c;他是一个key-value结构。我们来深入了解一下。 1.8之前用的数组加链表 1.8之后用的数组加链表加红黑树&#xff0c;当链表数量大于8时&#xff0c;将链表转为红黑树。当红黑书节点小于6又会转为链表。 浅析HashMap的put()方…

C语言 循环控制流程的跳转语句

本文 我们来说 控制流程的跳转语句 C语言 提供三种 控制流程的跳转语句 1. break 语句 我们之前讲 switch 时 大家已经看到过这个 break 了 作用是跳出当前 switch 在循环中 它的作用也差不多 这里 我们举个生活中的例子 例如 我们在操场上跑步 计划跑十圈 但是 还没跑完 我…

压缩和归档库-LZ4介绍

1.简介 LZ4是一种快速的压缩算法&#xff0c;提供压缩和解压缩的速度&#xff0c;而牺牲了压缩率。它被设计用于快速的数据压缩和解压缩&#xff0c;特别是用于数据存储和传输。LZ4通常用于需要高速数据处理的场景&#xff0c;如数据库、日志文件处理和实时数据传输。 LZ4的特…

【LLM 论文】Least-to-Most Prompting 让 LLM 实现复杂推理

论文&#xff1a;Least-to-Most Prompting Enables Complex Reasoning in Large Language Models ⭐⭐⭐ Google Research, ICLR 2023 论文速读 Chain-of-Thought&#xff08;CoT&#xff09; prompting 的方法通过结合 few-show prompt 的思路&#xff0c;让 LLM 能够挑战更具…

上位机图像处理和嵌入式模块部署(树莓派4b和c++新版本的问题)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 自己读书的时候是03年&#xff0c;学习c也是差不多04年开始&#xff0c;到现在基本上20年了。这20年过程当中&#xff0c;其实c的语言版本一直是在…

phpstudy(MySQL启动又立马停止)问题的解决办法

方法一&#xff1a;查看本地安装的MySQL有没有启动 1.鼠标右击开始按钮选择计算机管理 2.点击服务和应用程序 3.找到服务双击 4.找到MySQL服务 5.双击查看是否启动&#xff0c;如启动则停止他&#xff0c;然后确定&#xff0c;重新打开phpstudy,启动Mysql. 方法二&#xff…

【半夜学习MySQL】数据库概念详解探索数据库到底是如何存储的?

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 什么是数据库主流数据库与数据库分类数据库的基本使用数据库的启动及关闭查看配置文件与数据库存储位置连接数据库服务器服务…

Linux网络部分——SSH远程访问及控制

目录 一、配置OpenSSH服务端【☆】 1. ssh服务端配置 vim /etc/ssh/sshd_config 2.客户端连接验证 二、使用SSH客户端程序 1.ssh 远程登录 2.scp 远程复制 3.sftp 安全FTP 三、SSH的验证方式 1. 密钥对验证【☆】 2. 如何实现免密登录 【拓展】免交互创建密钥对和免交…