[数据结构初阶]队列
鼠鼠我呀,今天写一个基于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
感谢阅读,有不对的地方欢迎像本鼠拿捏玩偶一样拿捏鼠鼠捏!
相关文章:
[数据结构初阶]队列
鼠鼠我呀,今天写一个基于C语言关于队列的博客,如果有兴趣的读者老爷可以抽空看看,很希望的到各位老爷观点和点评捏! 在此今日,也祝各位小姐姐女生节快乐啊,愿笑容依旧灿烂如初阳,勇气与童真永不…...
MySQL学习Day27——MySQL事务日志
事务的隔离性由锁机制实现,而事务的原子性、一致性和持久性由事务的redo日志和undo日志来保证。其中REDO LOG称为重做日志,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性,redo log是存储引擎层生成的日志,记录的是物理级别上的页修改操作,主要为了保证…...
ETAS工具链ISOLAR-AB重要概念,RTE配置,ECU抽取
RTE配置界面,包含ECU抽取关联 首次配置RTE,出现需要勾选的抽取EXTRACT 创建System System制作SWC到ECU的Mapping System制作System Data 的Mapping...
蓝桥杯倒计时 43天 - 前缀和
思路:如果用n^2复杂度暴力会超时。nlogn 可以,利用前缀和化简,提前存储某个位置前的每个石头搬运到该位置和每个石头后搬运到该位置的前缀和On最后直接输出 On。排序花 nlogn #include<bits/stdc.h> using namespace std; typedef pai…...
【Web - 框架 - Vue】随笔 - Vue的简单使用(01) - 快速上手
【Web - 框架 - Vue】随笔 - Vue的简单使用(01) - 快速上手 Vue模板代码 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>模板</title> </head> <body> <div></di…...
【简说八股】Redisson的守护线程是怎么实现的
Redisson Redisson 是一个 Java 语言实现的 Redis SDK 客户端,在使用分布式锁时,它就采用了「自动续期」的方案来避免锁过期,这个守护线程我们一般也把它叫做「看门狗」线程。 Redission是一个在Java环境中使用的开源的分布式缓存和分布式锁实…...
WPS/Office 好用的Word插件-查找替换
例如:一片文档:…………泰山…………泰(少打了山字)………… 要是把“泰”查找替换为“泰山”,就会把前面的“泰山”变成“泰山山”,这种问题除了再把“泰山山”查找替换为“泰山”,有没有更简单…...
Go 简单设计和实现可扩展、高性能的泛型本地缓存
相信大家对于缓存这个词都不陌生,但凡追求高性能的业务场景,一般都会使用缓存,它可以提高数据的检索速度,减少数据库的压力。缓存大体分为两类:本地缓存和分布式缓存(如 Redis)。本地缓存适用于…...
Vue.js 深度解析:模板编译原理与过程
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
Java多线程——如何保证原子性
目录 引出原子性保障原子性CAS 创建线程有几种方式?方式1:继承Thread创建线程方式2:通过Runnable方式3:通过Callable创建线程方式4:通过线程池概述ThreadPoolExecutor API代码实现源码分析工作原理:线程池的…...
stm32消息和邮箱使用
邮箱管里介绍 邮箱是C/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量。该指针指向一个包含了特定“消息”的数据结构。为了在C/OS-II中使用邮箱,必须将OS_CFG.H中的OS_MBOX_EN常数置为1。使用邮箱之前,必须先建立该邮箱。该操…...
银行数字化转型导师坚鹏:银行数字化转型案例研究
银行数字化转型案例研究 课程背景: 数字化背景下,很多银行存在以下问题: 不清楚银行科技金融数智化案例? 不清楚银行供应链金融数智化案例? 不清楚银行普惠金融数智化案例? 不清楚银行跨境金融数智…...
142.乐理基础-音程的构唱练习
内容参考于:三分钟音乐社 上一个内容:141.乐理基础-男声女声音域、模唱、记谱与实际音高等若干问题说明-CSDN博客 本次内容最好去看视频: https://apphq3npvwg1926.h5.xiaoeknow.com/p/course/column/p_5fdc7b16e4b0231ba88d94f4?l_progra…...
【比较mybatis、lazy、sqltoy、mybatis-flex操作数据】操作批量新增、分页查询(二)
orm框架使用性能比较 环境: idea jdk17 spring boot 3.0.7 mysql 8.0比较mybatis、lazy、sqltoy、mybatis-flex操作数据 测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本mybatis☑️☑️3.5.4sqltoy☑️☑️5.2.98lazy✖️☑️1.2.4-JDK17-SNAPS…...
每日OJ题_链表②_力扣24. 两两交换链表中的节点
目录 力扣24. 两两交换链表中的节点 解析代码 力扣24. 两两交换链表中的节点 24. 两两交换链表中的节点 难度 中等 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即&…...
C语言数据类型详解及相关题——各种奇奇怪怪的偏难怪
文章目录 一、C语言基本数据类型溢出 二、存储原理符号位原码反码补码补码操作的例子 三、赋值中的类型转换常见返回类型——巨坑总结 一、C语言基本数据类型 溢出 因为数据范围(即存储单元的位的数量)的限制,可以表达的位数是有限的。 溢出…...
经典语义分割(二)医学图像分割模型UNet
经典语义分割(二)医学图像分割模型UNet 我们之前介绍了全卷积神经网络( FCN) ,FCN是基于深度学习的语义分割算法的开山之作。 今天我们介绍另一个语义分割的经典模型—UNet,它兼具轻量化与高性能,通常作为语义分割任务的基线测试模型&#x…...
三天学会阿里分布式事务框架Seata-seata事务日志mysql持久化配置
锋哥原创的分布式事务框架Seata视频教程: 实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)共计10条视频&…...
C语言-简单实现单片机中的malloc示例
概述 在实际项目中,有些单片机资源紧缺,需要mallloc内存,库又没有自带malloc函数时,此时,就需要手动编写,在此做个笔录。(已在项目上使用),还可进入对齐管理机制。 直接…...
外包干了2年,技术退步明显
先说一下自己的情况,研究生,19年进入广州某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

在此今日,也祝各位小姐姐女生节快乐啊,愿笑容依旧灿烂如初阳,勇气与童真永不退色!
运行结果如图,至于为什么是这些个结果,我们详细看以下鼠鼠的队列方案是如何实现的。



