数据结构 | 队列:从概念到实战

数据结构 | 队列:从概念到实战

个人主页-爱因斯晨

文章专栏-数据结构

继续加油!
在这里插入图片描述

文章目录

一、队列的基本概念

队列是一种先进先出(FIFO,First In First Out) 的线性数据结构,仅允许在一端进行插入操作(队尾),另一端进行删除操作(队头)。

生活中的队列场景:

  • 银行窗口排队办理业务
  • 打印机任务队列
  • 消息队列中的消息传递

二、队列的核心操作

  1. 初始化(InitQueue:创建一个空队列
  2. 入队(EnQueue:在队尾插入元素
  3. 出队(DeQueue:从队头删除元素
  4. 获取队头元素(GetFront:返回队头元素值
  5. 判空(IsEmpty:判断队列是否为空
  6. 销毁(DestroyQueue:释放队列占用的内存

三、C 语言实现队列

3.1 顺序队列(数组实现)

顺序队列使用数组存储元素,通过队头指针(front)和队尾指针(rear)标记队列边界。

#include<stdio.h>#include<stdlib.h>#defineMAX_SIZE100// 队列最大容量// 顺序队列结构体typedefstruct{int data[MAX_SIZE];int front;// 队头指针(指向队头元素)int rear;// 队尾指针(指向队尾元素的下一个位置)} SeqQueue;// 初始化队列voidInitQueue(SeqQueue *q){ q->front =0; q->rear =0;}// 判空intIsEmpty(SeqQueue *q){return q->front == q->rear;}// 判满intIsFull(SeqQueue *q){return(q->rear +1)% MAX_SIZE == q->front;// 预留一个空间区分空满}// 入队intEnQueue(SeqQueue *q,int value){if(IsFull(q)){printf("队列已满,无法入队\n");return0;// 入队失败} q->data[q->rear]= value; q->rear =(q->rear +1)% MAX_SIZE;// 循环移动队尾指针return1;// 入队成功}// 出队intDeQueue(SeqQueue *q,int*value){if(IsEmpty(q)){printf("队列为空,无法出队\n");return0;// 出队失败}*value = q->data[q->front]; q->front =(q->front +1)% MAX_SIZE;// 循环移动队头指针return1;// 出队成功}// 获取队头元素intGetFront(SeqQueue *q,int*value){if(IsEmpty(q)){printf("队列为空,无队头元素\n");return0;}*value = q->data[q->front];return1;}// 测试顺序队列intmain(){ SeqQueue q;InitQueue(&q);// 入队操作EnQueue(&q,10);EnQueue(&q,20);EnQueue(&q,30);// 获取队头元素int frontVal;GetFront(&q,&frontVal);printf("队头元素:%d\n", frontVal);// 输出:10// 出队操作int deVal;DeQueue(&q,&deVal);printf("出队元素:%d\n", deVal);// 输出:10// 再次获取队头GetFront(&q,&frontVal);printf("新队头元素:%d\n", frontVal);// 输出:20return0;}

顺序队列特点

  • 优点:实现简单,访问速度快
  • 缺点:容量固定,存在 “假溢出” 问题(需用循环队列优化)

3.2 链式队列(链表实现)

链式队列使用链表存储元素,队头指针指向头节点,队尾指针指向尾节点。

#include<stdio.h>#include<stdlib.h>// 节点结构体typedefstructNode{int data;structNode*next;} Node;// 链式队列结构体typedefstruct{ Node *front;// 队头指针(指向头节点) Node *rear;// 队尾指针(指向尾节点)} LinkQueue;// 初始化队列voidInitQueue(LinkQueue *q){// 创建头节点(不存储数据) Node *head =(Node*)malloc(sizeof(Node)); head->next =NULL; q->front = head; q->rear = head;}// 判空intIsEmpty(LinkQueue *q){return q->front == q->rear;}// 入队voidEnQueue(LinkQueue *q,int value){// 创建新节点 Node *newNode =(Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next =NULL;// 插入到队尾 q->rear->next = newNode; q->rear = newNode;// 更新队尾指针}// 出队intDeQueue(LinkQueue *q,int*value){if(IsEmpty(q)){printf("队列为空,无法出队\n");return0;} Node *temp = q->front->next;// 待删除节点*value = temp->data; q->front->next = temp->next;// 如果删除的是最后一个节点,需更新队尾指针if(q->rear == temp){ q->rear = q->front;}free(temp);// 释放节点内存return1;}// 获取队头元素intGetFront(LinkQueue *q,int*value){if(IsEmpty(q)){printf("队列为空,无队头元素\n");return0;}*value = q->front->next->data;return1;}// 销毁队列voidDestroyQueue(LinkQueue *q){// 释放所有节点while(q->front !=NULL){ q->rear = q->front->next;free(q->front); q->front = q->rear;}}// 测试链式队列intmain(){ LinkQueue q;InitQueue(&q);// 入队EnQueue(&q,100);EnQueue(&q,200);EnQueue(&q,300);// 获取队头int frontVal;GetFront(&q,&frontVal);printf("队头元素:%d\n", frontVal);// 输出:100// 出队int deVal;DeQueue(&q,&deVal);printf("出队元素:%d\n", deVal);// 输出:100// 销毁队列DestroyQueue(&q);return0;}

链式队列特点

  • 优点:容量动态扩展,不存在溢出问题
  • 缺点:需要额外空间存储指针,操作稍复杂

四、队列的应用场景

  1. 广度优先搜索(BFS):在二叉树层次遍历、图的遍历中常用
  2. 缓冲处理:如键盘输入缓冲、网络数据接收缓冲
  3. 任务调度:操作系统中的进程调度、线程池任务调度
  4. 消息传递:分布式系统中的消息队列(如 RabbitMQ)

五、两种实现的对比选择

场景推荐实现理由
已知数据量且固定顺序队列效率更高,无需额外指针开销
数据量动态变化链式队列避免空间浪费和溢出问题
频繁插入删除链式队列操作更高效(O (1) 时间复杂度)
对内存使用敏感顺序队列内存连续分配,缓存利用率高

Read more

MySQL 从入门到精通完全教程

目录 1. 前言 2. MySQL 基础认知 3. MySQL 安装与配置 4. MySQL 核心语法 5. 高级查询技巧 6. MySQL 函数 7. 数据约束 8. 事务管理 9. 索引优化 10. 存储过程与函数 11. 用户与权限管理 12. 性能优化实战 13. 常见问题与解决方案 1. 前言 1.1 什么是MySQL? MySQL 是一款开源的关系型数据库管理系统(RDBMS),基于SQL(结构化查询语言)实现数据管理,广泛应用于Web开发(如PHP+MySQL、Python+MySQL),特点是轻量、高效、跨平台、

By Ne0inhk
Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构

Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构 前言 在鸿蒙(OpenHarmony)生态迈向工业级运维、涉及大量后台守护进程(Daemon)、系统日志审计及开发者工具链(CLI)开发的背景下,如何为枯燥的纯文本终端注入具备视觉层级的色彩与样式,已成为提升调试效率与故障定位速度的“视觉助推器”。在鸿蒙设备这类强调 AOT 极致性能与低级别 shell 交互的环境下,如果应用依然依赖基础的单色字符串输出日志,由于由于信息流极其庞大且缺乏重点,极易由于由于“视觉疲劳”导致关键系统警告或业务异常被淹没在海量数据中。 我们需要一种能够支持 ANSI 转义序列、具备富文本样式(加粗/背景色)且兼容多种终端模拟器的文本渲染方案。 ansi_text 为 Flutter 开发者引入了基于标准

By Ne0inhk
Spring Web MVC从入门到实战

Spring Web MVC从入门到实战

—JavaEE专栏— 1. Spring Web MVC核心概念 1.1 什么是Spring Web MVC Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就包含在Spring框架中,其正式名称来源于源模块名称(spring-webmvc),通常简称为Spring MVC。 官方定义:Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. Servlet是Java Web开发的规范,定义了动态页面开发的技术标准,而Tomcat、Weblogic等Servlet容器则是该规范的具体实现,

By Ne0inhk

前端常用字符串/数组操作(含相关手撕)

字符串转数组的方法 1. split() - 最常用的方法 功能描述:使用指定的分隔符将字符串分割成字符串数组 语法: str.split([separator[, limit]]) 参数: * separator:指定表示每个拆分点的字符串,如果省略,则返回包含整个字符串的数组 * limit:可选,限制返回的数组片段数量 示例: const str = "apple,banana,orange"; const arr = str.split(","); // 结果: ["apple", "banana", "orange"] const str2 = "hello"; const

By Ne0inhk