长沙it公司杭州seo平台
2026/3/29 0:44:15 网站建设 项目流程
长沙it公司,杭州seo平台,上海市网站设计公司,国内最最早做虚拟货币的网站#x1f3e0;个人主页#xff1a;黎雁 #x1f3ac;作者简介#xff1a;C/C/JAVA后端开发学习者 ❄️个人专栏#xff1a;C语言、数据结构#xff08;C语言#xff09;、EasyX、游戏、规划、程序人生 ✨ 从来绝巘须孤往#xff0c;万里同尘即玉京 文章目录栈与队列之队…个人主页黎雁作者简介C/C/JAVA后端开发学习者❄️个人专栏C语言、数据结构C语言、EasyX、游戏、规划、程序人生✨ 从来绝巘须孤往万里同尘即玉京文章目录栈与队列之队列入门攻略从核心概念到链表实现✨文章摘要一、知识回顾栈 vs 队列的核心差异二、队列的核心概念什么是“先进先出”1. 队列的定义2. 队列的关键操作术语3. 队列的实现方式对比数组 vs 链表三、队列的工程化实现链表版队列完整代码1. 头文件定义queue.h接口声明2. 源文件实现queue.c核心逻辑四、核心易错点解析边界场景处理⚠️五、写在最后栈与队列之队列入门攻略从核心概念到链表实现✨你好欢迎来到线性表系列栈与队列篇的第二篇内容在上一篇中我们吃透了“后进先出”的栈结构而今天的主角——队列恰恰是栈的“反向搭档”它遵循“先进先出”原则在日常开发和算法解题中同样不可或缺比如消息队列、任务排队、二叉树层序遍历等场景都能看到它的身影。继栈的数组实现后我们这篇将聚焦队列的核心知识从概念到实现手把手带你搞定这个“排队专用”的线性表文章摘要本文为线性表系列栈与队列篇第二篇入门内容聚焦队列这一受限线性表。通俗讲解队列“先进先出”的核心特性对比数组与链表两种实现方式的优劣并选定单向链表为最优方案。通过工程化的头文件源文件结构完整实现队列的初始化、销毁、入队、出队等核心操作详解队头队尾指针的边界处理细节补充空队列、单节点队列等特殊场景的处理逻辑零基础吃透队列的底层实现。阅读时长约20分钟阅读建议基础薄弱者先理解队列“先进先出”特性再对照代码梳理指针逻辑工程开发者重点关注内存释放、队空/队满判断等健壮性细节面试备考者牢记队列的特性、实现方式及典型应用场景查漏补缺者直接查看出队操作中单节点队列的特殊处理逻辑一、知识回顾栈 vs 队列的核心差异在学习队列之前我们先对比栈和队列的核心区别快速建立认知数据结构核心特性操作端最优实现方式栈后进先出LIFO仅栈顶一端数组尾插尾删队列先进先出FIFO队尾入、队头出链表头删尾插简单总结栈是“一口进出”队列是“一头进、另一头出”二、队列的核心概念什么是“先进先出”1. 队列的定义队列是一种特殊的线性表只允许在一端插入元素队尾在另一端删除元素队头遵循先进先出FIFO First In First Out原则。生活中的队列例子随处可见排队买奶茶先排队的人先买到奶茶 → 完美契合“先进先出”打印机打印任务先提交的任务先打印 → 典型的队列应用消息队列先产生的消息先被消费 → 工程中最常用的队列场景2. 队列的关键操作术语操作名称说明操作位置入队/进队向队列中添加元素队尾唯一入队端出队/离队从队列中删除元素队头唯一出队端队头允许删除元素的一端-队尾允许插入元素的一端-3. 队列的实现方式对比数组 vs 链表队列同样有两种实现方式我们详细分析优劣选择最优方案实现方式核心思路优点缺点数组队尾入队尾插、队头出队头删实现简单、随机访问快队头出队需挪动所有元素时间复杂度O(N)效率极低链表推荐单向链表队尾入队尾插、队头出队头删用tail指针记录队尾避免找尾① 入队/出队效率O(1) ② 按需分配内存无需扩容需额外维护队头/队尾指针处理空队列/单节点队列边界✅结论单向链表实现队列是最优选择链表头删、尾插的时间复杂度都是O(1)完美匹配队列的操作需求只需维护head队头和tail队尾两个指针即可高效完成所有操作避免了数组出队时挪动元素的性能损耗三、队列的工程化实现链表版队列完整代码我们依旧采用“头文件源文件”的工程化结构实现队列保证代码规范性。1. 头文件定义queue.h接口声明#pragmaonce#includestdio.h#includestdbool.h#includeassert.h#includestdlib.h// 定义队列存储的数据类型typedefintQDataType;// 队列节点结构体单向链表节点typedefstructQueueNode{structQueueNode*next;// 指向下一个节点的指针QDataType data;// 节点存储的数据}QNode;// 队列结构体维护队头、队尾指针typedefstructQueue{QNode*head;// 队头指针出队端QNode*tail;// 队尾指针入队端}Queue;// 队列核心操作接口voidQueueInit(Queue*pq);// 初始化队列voidQueueDestroy(Queue*pq);// 销毁队列释放内存voidQueuePush(Queue*pq,QDataType x);// 入队队尾插入voidQueuePop(Queue*pq);// 出队队头删除QDataTypeQueueFront(Queue*pq);// 获取队头元素QDataTypeQueueBack(Queue*pq);// 获取队尾元素intQueueSize(Queue*pq);// 获取队列元素个数boolQueueEmpty(Queue*pq);// 判断队列是否为空2. 源文件实现queue.c核心逻辑#includequeue.h// 初始化队列voidQueueInit(Queue*pq){assert(pq);// 确保队列指针不为NULLpq-headNULL;// 初始队头为空pq-tailNULL;// 初始队尾为空}// 销毁队列遍历释放所有节点voidQueueDestroy(Queue*pq){assert(pq);QNode*curpq-head;while(cur)// 逐个释放节点{QNode*nextcur-next;// 保存下一个节点free(cur);curnext;}// 重置指针防止野指针pq-headNULL;pq-tailNULL;}// 入队队尾插入voidQueuePush(Queue*pq,QDataType x){assert(pq);// 创建新节点QNode*newnode(QNode*)malloc(sizeof(QNode));if(newnodeNULL){perror(malloc fail);exit(1);}newnode-datax;newnode-nextNULL;// 处理空队列第一个节点if(pq-tailNULL){pq-headnewnode;pq-tailnewnode;}else// 队列非空尾插{pq-tail-nextnewnode;pq-tailnewnode;// 更新队尾指针}}// 出队队头删除voidQueuePop(Queue*pq){assert(pq);assert(!QueueEmpty(pq));// 队空禁止出队// 处理单节点队列删除后队头队尾都为空if(pq-head-nextNULL){free(pq-head);pq-headNULL;pq-tailNULL;}else// 多节点队列头删{QNode*nextpq-head-next;free(pq-head);pq-headnext;// 更新队头指针}}// 获取队头元素QDataTypeQueueFront(Queue*pq){assert(pq);assert(!QueueEmpty(pq));// 队空禁止获取returnpq-head-data;}// 获取队尾元素QDataTypeQueueBack(Queue*pq){assert(pq);assert(!QueueEmpty(pq));// 队空禁止获取returnpq-tail-data;}// 获取队列元素个数intQueueSize(Queue*pq){assert(pq);intsize0;QNode*curpq-head;while(cur)// 遍历统计节点数{size;curcur-next;}returnsize;}// 判断队列是否为空boolQueueEmpty(Queue*pq){assert(pq);returnpq-headNULL;// 队头为空则队列空}四、核心易错点解析边界场景处理⚠️队列实现中最容易出错的是边界场景我们重点梳理空队列入队需同时更新head和tail指针否则会出现tail为NULL的错误单节点队列出队删除后必须将head和tail都置NULL否则tail会指向已释放的节点野指针出队前判空必须用assert(!QueueEmpty(pq))防止空队列出队避免访问NULL指针五、写在最后恭喜你这一篇中你已经掌握了队列的核心知识理解了队列“先进先出”的核心特性对比了和栈的关键差异选定了链表作为队列的最优实现方式吃透了头删尾插的逻辑完成了队列的工程化代码实现掌握了边界场景的处理技巧队列和栈是数据结构的“基础搭档”二者结合能解决很多复杂问题算法层面二叉树层序遍历、BFS广度优先搜索依赖队列工程层面消息队列、任务调度、限流削峰都离不开队列下一篇我们将进入实战环节用栈和队列解决经典OJ题把理论转化为解题能力点赞收藏关注跟着系列内容一步步吃透栈和队列你的支持是我创作的最大动力

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询