news 2026/7/20 14:17:21

队列的链式实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
队列的链式实现

文章目录

  • 队列的链式实现
  • 代码实现
    • 结构定义与初始化
      • 带头结点
      • 不带头结点
    • 入队(尾插法)
      • 带头结点
      • 不带头结点
    • 出队
      • 带头结点
      • 不带头结点
    • 查队头
    • 销毁

队列的链式实现

链队列是队列的链式存储结构,本质上是操作受限单链表。其解决了顺序队列(循环队列)“容量固定、可能溢出”的缺陷。
链队列需要两个指针:

  • front(队头指针):指向头结点(注意:不是第一个数据结点)。头结点的data闲置,next指向真正的首元结点。
  • rear(队尾指针):指向最后一个数据结点(尾结点)。

带头结点后,空队时front == rear(均指向头结点),所有操作逻辑完全统一

图示:

空队: front(rear) -> [头结点 | next=NULL] 入队10: front -> [头结点 | next] -> [10 | NULL] rear-^ 入队20: front -> [头结点 | next] -> [10 | next] -> [20 | NULL] rear -^

代码实现

结构定义与初始化

与顺序队列不同,链队列通常将frontrear封装在一个结构体中,便于函数传参。

带头结点

#include<stdio.h>#include<stdlib.h>#include<stdbool.h>// ① 结点定义(与单链表完全一样)typedefstructLNode{intdata;structLNode*next;}LNode;// ② 链队列定义(封装了队头和队尾指针)typedefstruct{LNode*front;// 队头指针(指向头结点)LNode*rear;// 队尾指针(指向最后一个结点)}LinkQueue;// 带头结点// 初始化 :创建空队列(创建头结点)boolInitQueue(LinkQueue&Q){// 1. 申请头结点空间 队尾指针也指向头结点(表示空队)Q.front=Q.rear=(LNode*)malloc(sizeof(LNode));if(Q.front==NULL)returnfalse;// 内存分配失败// 2. 头结点的 next 置空Q.front->next=NULL;returntrue;}// 判空boolQueueEmpty(LinkQueue Q){returnQ.front==Q.rear;// 或者 Q.front->next == NULL 若 front = rear 则为空}// 判满 链队列不存在 “满 ”的概念!// 唯一的限制是堆内存耗尽。通常不写判满函数,而是在入队时检测 malloc 返回值。boolQueueFull(LinkQueue Q){returnfalse;// 理论永远不满(只要内存够)}

不带头结点

#include<stdio.h>#include<stdlib.h>#include<stdbool.h>typedefstructLNode{intdata;structLNode*next;}LNode;typedefstruct{LNode*front;// 队头指针:指向第一个数据结点(不是头结点!!!!!)LNode*rear;// 队尾指针:指向最后一个数据结点}LinkQueue;// 不带头结点// 初始化 创建空队列(不分配头结点)voidInitQueue(LinkQueue&Q){Q.front=NULL;// 直接置空Q.rear=NULL;// 直接置空}// 判空boolQueueEmpty(LinkQueue Q){returnQ.front==NULL;// 只要队头为空,队列就为空// 也可以这样判断:Q.rear == NULL;}

入队(尾插法)

带头结点

步骤:新建结点 → 接到rear后面 → 更新rear为新结点

// 带头结点// 入队 在队尾(rear 后面)插入元素 eboolEnQueue(LinkQueue&Q,inte){// 1. 申请新结点空间LNode*s=(LNode*)malloc(sizeof(LNode));if(s==NULL)returnfalse;// 内存耗尽,相当于 “队满 ”// 2. 初始化新结点s->data=e;s->next=NULL;// 3. 将新结点挂到当前尾结点后面Q.rear->next=s;// 4. 尾指针后移(指向新的尾结点)Q.rear=s;returntrue;}

不带头结点

// 不带头结点// 入队 在队尾插入元素 eboolEnQueue(LinkQueue&Q,inte){LNode*s=(LNode*)malloc(sizeof(LNode));if(s==NULL)returnfalse;s->data=e;s->next=NULL;// 必须特别判断是不是第一个结点// 不带头结点的队列,第一个元素入队时需要特别处理if(Q.front==NULL){// 情况1:空队,front 和 rear 都指向新结点Q.front=s;// 修改队头队尾指针Q.rear=s;}else{// 情况2:非空队,挂在尾结点后面Q.rear->next=s;// 新结点插入到 rear 结点之后Q.rear=s;// 修改 rear 指针}returntrue;}

出队

删除队头第一个有效结点
特殊边界:如果删除后队列为空,需要将rear重置回头结点,防止rear悬空。

带头结点

删除头结点的后继。

// 带头结点// 出队 删除队头元素,并通过 e 带回其值boolDeQueue(LinkQueue&Q,int&e){// 1. 判空if(Q.front==Q.rear)returnfalse;// 2. p 指向首元结点(第一个数据结点)LNode*p=Q.front->next;e=p->data;// 保存数据// 3. 头结点跨过 p,指向 p 的下一个结点Q.front->next=p->next;// 注意:如果 p 恰好是最后一个结点(即出队后队列变空)// 必须把 rear 重新指向头结点,否则 rear 将指向已释放的内存!if(p==Q.rear){Q.rear=Q.front;}// 4. 释放 p 结点内存free(p);returntrue;}

不带头结点

// 不带头结点// 出队 删除队头元素,并通过 e 带回其值boolDeQueue(LinkQueue&Q,int&e){// 1. 判空if(Q.front==NULL)returnfalse;// 2. p 指向队头结点(直接就是 front)LNode*p=Q.front;e=p->data;// 3. 队头指针后移(指向下一个数据结点)Q.front=p->next;// 如果删除的是唯一结点(出队后队列变空)if(Q.front==NULL){// 必须把 rear 也置为 NULL,否则 rear 指向已释放的内存!Q.rear=NULL;}// 或这样写// if(Q.rear == p ){// Q.rear = NULL;// Q.front = NULL;// }free(p);returntrue;}

查队头

// 带头结点// 查队头 只读操作,不删除元素boolGetHead(LinkQueue Q,int&e){if(Q.front==Q.rear)// 空队returnfalse;e=Q.front->next->data;// 头结点的后继才是第一个数据returntrue;}// 不带头结点// 查队头 只读操作boolGetHead(LinkQueue Q,int&e){if(Q.front==NULL)returnfalse;e=Q.front->data;// front 直接指向数据结点,无需绕 ->nextreturntrue;}

销毁

// 带头结点// 销毁 释放所有结点(包括头结点)voidDestroyQueue(LinkQueue&Q){LNode*p=Q.front;// p 从头结点开始while(p!=NULL){LNode*q=p;p=p->next;free(q);}// 防止野指针(虽然 Q 是引用,但置空是好习惯)Q.front=NULL;Q.rear=NULL;}// 不带头结点// 销毁 释放所有数据结点voidDestroyQueue(LinkQueue&Q){LNode*p=Q.front;while(p!=NULL){LNode*q=p;p=p->next;free(q);}Q.front=NULL;Q.rear=NULL;}

链队列是采用链式存储结构的队列,通常使用带头结点的单链表实现,并附设frontrear两个指针分别指向头结点和尾结点。入队操作对应单链表的尾插法(rear->next = s; rear = s;),出队操作对应删除头结点的后继结点。在出队时,若被删结点是尾结点,必须将rear重置为front。链队列克服了顺序队列容量固定的缺陷,入队、出队、判空操作的时间复杂度均为O(1)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 14:16:39

量子计算与AI轻量化技术突破解析

1. 每日新闻播报&#xff08;2月13日&#xff09;精选内容作为一名长期关注时事的媒体从业者&#xff0c;我每天都会整理当天最具价值的新闻要点。今天&#xff08;2月13日&#xff09;的新闻涵盖了科技突破、社会热点和国际动态等多个领域&#xff0c;以下是经过筛选的核心内容…

作者头像 李华
网站建设 2026/7/20 14:16:16

提升Calibre图书管理效率:NLCISBNPlugin与其他元数据插件对比分析

提升Calibre图书管理效率&#xff1a;NLCISBNPlugin与其他元数据插件对比分析 【免费下载链接】NLCISBNPlugin 基于中国国家图书馆ISBN检索的calibre的source/metadata插件。https://doiiars.com/article/NLCISBNPlugin 项目地址: https://gitcode.com/gh_mirrors/nl/NLCISBN…

作者头像 李华
网站建设 2026/7/20 14:14:59

鸿蒙 PC Markdown 编辑器标签系统:十二标签上限与桌面交互

鸿蒙 PC Markdown 编辑器标签系统&#xff1a;十二标签上限与桌面交互 标签栏是多文档状态的可视投影。它要表达活动文档、文件名、未保存状态、关闭动作和新建入口&#xff0c;还要在自由窗口缩窄时保持可操作。无限标签看似自由&#xff0c;实际会让完整 EditorState、撤销历…

作者头像 李华
网站建设 2026/7/20 14:14:15

ring-mqtt深度解析:实现Ring设备与Home Assistant完美集成

ring-mqtt深度解析&#xff1a;实现Ring设备与Home Assistant完美集成 【免费下载链接】ring-mqtt Ring devices to MQTT Bridge 项目地址: https://gitcode.com/gh_mirrors/ri/ring-mqtt ring-mqtt是一款强大的开源工具&#xff0c;它能将Ring设备与本地MQTT代理桥接&a…

作者头像 李华
网站建设 2026/7/20 14:13:36

二、蜂鸣器

文章目录1、蜂鸣器响小灯亮1.1效果图1.2代码块1、蜂鸣器响小灯亮 蜂鸣器“滴滴”响&#xff0c;8个LED灯也亮 1.1效果图 1.2代码块 #include <reg51.h> // 包含头文件 // 定义单个 LED 的端口映射【sbit 变量名 端口^位号;】 sbit BUZZER P3^7;// 延时函数 void dela…

作者头像 李华