[数据结构初阶]队列

鼠鼠我呀,今天写一个基于C语言关于队列的博客,如果有兴趣的读者老爷可以抽空看看,很希望的到各位老爷观点和点评捏!

在此今日,也祝各位小姐姐女生节快乐啊,愿笑容依旧灿烂如初阳,勇气与童真永不退色!

目录

1.队列的概念及结构

 2.对列的实现 

2.1.queue.h

2.2.queue.c

2.3.test.c

2.4.定义队列

2.5.初始化队列

2.6.队尾入队列

2.7.对头出队列

2.8.获取队列队头元素

2.9.获取队列队尾元素

2.10.获取队列中有效元素的个数

2.11.检测队列是否为空,如果为空返回非零结果,非空返回0

2.12.销毁队列 

 3.分析运行结果

4.ending


 

1.队列的概念及结构

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

队尾:进行插入操作的一端称为队尾。

对头:进行删除操作的一端称为队头 。

咱们画一个队列的想象图就很好理解上面几个概念:

其实很好理解,队列里面的数据元素就像排队一样,先进入队列的数据元素当然先出队列了。

 2.对列的实现 

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

而队列用链表实现的方案也是多种多样,只要满足队列的定义即可。鼠鼠我今天写一个方案(本方案基于无头单向非循环链表)各位佬们可以看看啊,俺先把三个文件和运行结果呈现如下:

2.1.queue.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int QDatatype;typedef struct QNode
{QDatatype _data;struct  QNode* _next;
}QNode;typedef struct Queue
{int k;QNode* head;QNode* tail;
}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
bool QueueEmpty(Queue* q);//销毁队列
void QueueDestory(Queue* q);

2.2.queue.c

#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"void QueueInit(Queue* q)
{assert(q);q->head = q->tail = NULL;q->k = 0;
}void QueuePush(Queue* q, QDatatype data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("malloc fail");return;}tmp->_data = data;tmp->_next = NULL;if (q->tail == NULL){q->head = q->tail = tmp;}else{q->tail->_next = tmp;q->tail = tmp;}q->k++;
}void QueuePop(Queue* q)
{assert(q);assert(q->k > 0);QNode* next = q->head->_next;free(q->head);q->head = next;if (q->head == NULL){q->tail = NULL;}q->k--;
}QDatatype QueueFront(Queue* q)
{assert(q);assert(q->k > 0);return q->head->_data;
}QDatatype QueueBack(Queue* q)
{assert(q);assert(q->k > 0);return q->tail->_data;
}int QueueSize(Queue* q)
{assert(q);return q->k;
}bool QueueEmpty(Queue* q)
{assert(q);return q->tail == NULL;
}void QueueDestory(Queue* q)
{assert(q);QNode* tmp = q->head;while (tmp){QNode* next = tmp->_next;free(tmp);tmp = next;}q->k = 0;q->head = q->tail = NULL;
}

2.3.test.c

#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"int main()
{Queue q;QueueInit(&q);QueuePush(&q, 0);QueuePush(&q, 1);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);QueuePush(&q, 6);printf("%d\n", QueueSize(&q));printf("%d ", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d ", QueueFront(&q));QueuePop(&q);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));QueuePop(&q);}printf("\n%d\n", QueueSize(&q));QueueDestory(&q);return 0;
}

运行结果如图,至于为什么是这些个结果,我们详细看以下鼠鼠的队列方案是如何实现的。

2.4.定义队列

typedef int QDatatype;typedef struct QNode
{QDatatype _data;struct  QNode* _next;
}QNode;typedef struct Queue
{int k;QNode* head;QNode* tail;
}Queue;

老样子我们将int重命名成QDatatype,方便以后代码的维护。

让后定义并重命名结构体QNode充当队列节点 ,这些节点根据数据元素的入队列或者出队列按需申请或者释放。QNode中成员_data用来存放数据元素,QNode中成员_next用来链接下一个节点。

又由于基于无头单向非循环链表(以下简称链表)实现的队列在入队列和出队列时分别需要链表尾插和头删,而且经常需要知道队列中数据元素的个数,我们定义并重命名结构体Queue来维护上面需求:Queue中成员k用来记录队列中数据元素个数;成员head用来指向链表头节点;成员tail用来指向链表尾节点。

大概这样子:

2.5.初始化队列

void QueueInit(Queue* q)
{assert(q);q->head = q->tail = NULL;q->k = 0;
}

断言防止传入的结构体变量地址为空(因为这个地址不可能为空)。将head和tail置成NULL,将k置成0即可。 

2.6.队尾入队列

void QueuePush(Queue* q, QDatatype data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("malloc fail");return;}tmp->_data = data;tmp->_next = NULL;if (q->tail == NULL){q->head = q->tail = tmp;}else{q->tail->_next = tmp;q->tail = tmp;}q->k++;
}

断言防止传入的结构体变量地址为空(这点以下不在赘述)。 队尾入队列其实就是链表尾插,先动态申请一个结构体QNode空间充当新节点,这个新节点的存放好想插入的数据元素,再让新节点链接好队列(链接队列是要区分队列是否为空),k加一即可。

2.7.对头出队列

void QueuePop(Queue* q)
{assert(q);assert(q->k > 0);QNode* next = q->head->_next;free(q->head);q->head = next;if (q->head == NULL){q->tail = NULL;}q->k--;
}

断言防止队列为空仍然出队列。常规来说再进行链表头删、k减一即可完成出队列,但要注意如果队列中只有一个数据元素(或者说链表只有一个节点)时,如果按常规操作的话会使得tail变成野指针,用上面一个if语句很好处理问题。 

2.8.获取队列队头元素

QDatatype QueueFront(Queue* q)
{assert(q);assert(q->k > 0);return q->head->_data;
}

 断言防止队列为空仍然获取对头元素。返回head指向的节点成员_data即可。

2.9.获取队列队尾元素

QDatatype QueueBack(Queue* q)
{assert(q);assert(q->k > 0);return q->tail->_data;
}

  断言防止队列为空仍然获取对尾元素。返回tail指向的节点成员_data即可。

2.10.获取队列中有效元素的个数

int QueueSize(Queue* q)
{assert(q);return q->k;
}

根据设定可知,返回k即可。 

2.11.检测队列是否为空,如果为空返回非零结果,非空返回0

bool QueueEmpty(Queue* q)
{assert(q);return q->tail == NULL;
}

若tail指向NULL说明队列为空(或者说链表为空),则q->tail==NULL为真,返回真。若队列不为空逻辑跟队列为空逻辑相反,返回假。 

2.12.销毁队列 

void QueueDestory(Queue* q)
{assert(q);QNode* tmp = q->head;while (tmp){QNode* next = tmp->_next;free(tmp);tmp = next;}q->k = 0;q->head = q->tail = NULL;
}

遍历链表将节点(这些节点都是动态申请的)都释放掉,再将head和tail置成NULL,并将k置成0即可。

 3.分析运行结果

佬们请看:

第一条语句:定义一个结构体Queue变量q;

第二条语句:初始化结构体变量q;

第三条到第十条语句:数据元素0、1、1、2、3、4、5、6依次入队列,执行完后队列想象图为: 

第十一条语句:执行printf函数,打印队列有效元素个数为8并换行。

第十二条和第十三条语句:均执行printf函数,分别打印对头元素0和队尾元素6,换行。

第十四条语句: 执行printf函数,打印对头元素0。

第十五条语句:对头元素0出队列,执行完第十五条语句后队列想象图为:

接下来while循环:当队列不为空时,打印对头元素再对头元素出队列。所以分别打印1、1、2、3、4、5、6。执行完while循环后,队列为空(或者说链表为空)。

再接下来打印队列有效元素个数为0,印证队列为空。再销毁队列。

4.ending

感谢阅读,有不对的地方欢迎像本鼠拿捏玩偶一样拿捏鼠鼠捏!

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

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

相关文章

STM32CubeMX学习笔记16--- STM32内部FLASH

1. 内部FLASH简介 之前的文章中介绍过STM32F1利用SPI与外部FLASH&#xff08;W25QXX芯片&#xff09;通讯的例程&#xff0c;本例程将介绍STM32F1的内部FLASH&#xff0c;通过内部FLASH实现数据读写操作。 不同型号的STM32&#xff0c;其FLASH容量也有所不同&#xff0c;最小的…

nexus 简单运维

Nexus介绍 Nexus 是 Sonatype 公司发布的一款仓库&#xff08;Repository&#xff09;管理软件&#xff0c;常用来搭建 Maven 私服&#xff0c;所以也有人将 Nexus 称为“Maven仓库管理器”。 Nexus常用命令 进入安装目录 再进入bin目录 ​ cd /opt/nexus-3.13/nexus-3.13.…

【java】后序遍历二叉树

采用递归方式实现 节点类 public class Node {private int value;//父节点private Node fNode;//左节点private Node left;//右节点private Node right;//是否已经打印过private boolean sign false;public Node() {}public boolean isSign() {return sign;}public void setS…

未来AI发展趋势

引言 如何实现一个乌托邦式的社会呢&#xff1f;如果直接将人类社会分为两个阵营&#xff0c;一个是以旧人类为首的阵营&#xff0c;一个是以AI抚养的新人类阵营&#xff0c;其中新人类阵营的所有资源皆由旧人类阵营提供&#xff0c;且旧人类阵营的人类都经过了化学阉割无法生…

14:00面试,15:00就出来了,问的问题过于变态了。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到2月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

静态时序分析:典型与非典型时序路径的约束详解(一)

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 时序路径是静态时序分析中的一个重要概念&#xff0c;了解时序路径能帮助设计者更好地编写SDC脚本&#xff0c;本文旨在详细介绍时序路径相关内容。 首先给出时序…

Unity角色动画变成半跪\半蹲\下沉 的问题

导入的人物动画发生如图形态 解决方法&#xff1a;找到动画模型&#xff0c;Rig - AnimationType 改为Humanoid &#xff0c;然后Apply一下

高效加载大文件(pandas+dask)

一、仅用pd加载大文件(iterator、chunksize) 要使用Pandas进行高效加载超大文件&#xff0c;我们通常会利用其内置的分块&#xff08;chunk&#xff09;处理功能。不过&#xff0c;请注意&#xff0c;Pandas本身并不支持多线程读取文件&#xff1b;它更倾向于单线程中进行块处理…

千云GPS平台 -在k8s上部署Mysql

构建xtrabackup docker build -t registry.cn-zhangjiakou.aliyuncs.com/qy566/xtrabackup:8.0.34 --rm .部署进度 你可以通过运行以下命令查看启动进度: kubectl get pods -l app=mysql -n mysql-db --watch 测试mysql 发送客户端请求写入数据kubectl run mysql-client --…

解决cs不能生成Linux木马的问题

要解决的问题&#xff1a;众所周知&#xff0c;msf上面的shell或者是其他的shell想反弹给cs默认情况下是只支持windows的&#xff0c;因为cs的监听模块默认没有linux的&#xff0c;但是有些主机就是用linux搭建的&#xff0c;这可怎么办呢。就要用到一个插件CrossC2。 下载插件…

实操keepalived(高可用)+Nginx(四层代理+七层代理),实现高可用、负载均衡以及动静分离

一 vrrp技术 VRRP 相关术语 VRRP能够在不改变组网的情况下&#xff0c;将多台路由器虚拟成一个虚拟路由器&#xff0c;i通过配置虚拟路由器的IP地址为默认网关&#xff0c;实现网关的备份。 协议版本: VRRPv2 (常用) 和VRRPv3:0 VRRPv2仅适用于IPv4网络&#xff0c;VRRPv3适用…

[项目设计] 从零实现的高并发内存池(五)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 8 使用定长内存池脱离new 9. 释放对象时不传大小 10.性能优化 10.1…

[LeetCode][239]【学习日记】滑动窗口最大值——O(n)单调队列

题目 239. 滑动窗口最大值 难度&#xff1a;困难相关标签相关企业提示 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 示例 1…

雷赛控制卡的扩展IO连接

雷赛控制卡的扩展IO点无法控制问题处理 现象 因设备的上IO点较多&#xff0c;所以使用了多个雷赛32点位的IO扩展卡。上位机程序在控制输出IO时发现主模块IO和第一个扩展IO的输出可以控制。但第二个IO扩展卡和第三个IO扩展卡的输出控制不了。经排查出发现轴卡在初始化时只连接了…

校园小情书微信小程序,社区小程序前后端开源,校园表白墙交友小程序

功能 表白墙卖舍友步数旅行步数排行榜情侣脸漫画脸个人主页私信站内消息今日话题评论点赞收藏 效果图

2024年腾讯云学生服务器优惠活动「云+校园」政策解读

2024年腾讯云学生服务器优惠活动「云校园」&#xff0c;学生服务器优惠价格&#xff1a;轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年&#xff0c;轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年&#xff0c;CVM云服务器2核4G配置842.4元一年&…

几何工具的使用

Geometry - Creation 创建几何 CogCreateCircleTool&#xff1a;创建圆CogCreateEllipseTool:创建椭圆CogCreateLineBisectPointsTool&#xff1a;带有两个点的平行线CogCreateLineParallelTool:在某一点创建某条线的平行线CogCreateLinePerpendicularTool:在某一点创建某条线…

LT6813/ADBMS1818底层驱动---均衡控制

1、LT6813采用内部均衡的原理 2、平衡控制结构体 根据数据库中读取的控制值设置平衡。要为单元设置平衡&#xff0c;必须将相应的位写入配置寄存器中。LTC 驱动程序仅执行数据库中 BMS 写入的数据。 参数 ltc_stateLTC 状态机的状态pSpi接口指向 SPI 配置的指针pTxBuff &…

数据结构(八)——初识单链表

&#x1f600;前言 单链表是数据结构中最基本的一种链表结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含数据和指向下一个节点的指针。单链表具有灵活性和动态性&#xff0c;可以根据需要插入、删除和查找元素&#xff0c;适用于各种场景和问题的解决。 在本篇文章…

day7-网络编程

1>基于UDP的网络聊天室 Ser.c #include <myhead.h> #define SER_IP "10.211.55.9" // 服务器IP #define SER_PORT 9999struct user {char usrName[20];struct sockaddr_in cin; }; int main(int argc, char const *argv[]) {// 1.创建用于监听的套接字int…