news 2026/4/16 19:36:47

数据结构学习篇(7)---队列

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据结构学习篇(7)---队列

1. 队列的概念及结构

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

  • 入队列:进行插入操作的一端称为队尾。
  • 出队列:进行删除操作的一端称为队头。

队列和栈是有所不同的,比如入栈顺序是1 2 3 4,但是出栈顺序可以有多种,不一定是 1 2 3 4,因为它可以边进边出,所以是一个一对多的关系;而队列的入队列顺序和出队列顺序是一样的,是一个一对一的关系,正是基于队列的这种性质,它可以用于保持公平性(例如做一个抽号机:比如吃饭排队拿取号码,先来的先拿,后来的后拿)。

也可以利用队列来做一个好友推荐(广度优先遍历)

假如要给小徐推荐好友,那么就以小徐为起点,首先让小徐进入队列,然后让小徐出队列(第一圈结束)的同时,让小徐的好友小明和小王入队列,这也就意味着当小徐出队列时,队列中剩下的都是小徐的朋友,然后按照顺序让小明出队列,出队列的同时让小明的朋友入队列,然后让小王出队列(第二圈结束),出队列的同时让小王的朋友入队列,这时小徐的朋友都出队列了,剩下的都是小徐朋友的朋友(也就是处于第三圈上的好友),这个时候就可以将队列中的好友推荐给小徐,不断循环这个步骤,就可以一步一步扩大好友圈。

2. 队列的功能实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。那么确定了使用链表,就要考虑是使用双向链表还是单向链表,因为双向链表肯定是可以实现队列功能的,但是我们优先考虑能不能使用单链表来实现,如果单链表能实现,就不使用双向链表,因为单向链表比双向链表更加节省空间。

2.1 一级指针还是二级指针

在数据结构的学习中,已经讨论过很多次到底是用一级指针还是二级指针的问题,我也混淆了很久,最简单的记忆方法就是去看你到底要不要去通过形参ppehad改变实参plist,若不不想改变实参,那形参就直接用一级指针接收即可,如果想要通过形参改变实参,那么就使用二级指针接收,因为只有对二级指针进行一次解引用,才能读取到实参部分,然后对*pphead的改变,就相当于是对plist的改变。

在队列的实现中,因为队列的本质是单链表,我在学习单链表的过程中,是使用二级指针来完成相应的功能的,在学习双向链表中,是使用一级指针来完成相应的功能的,这是因为在双向链表中引入了“头节点”,也就是“哨兵位”,因为指向哨兵位的指针plist是不需要被改变的,所以用一级指针接收即可,这一点我在双向链表的章节中也提到过;所以对于这节中的队列,为了避免二级指针的繁琐,也直接使用一级指针来接收,但是是使用一种新的方式来解决这个问题:直接将指向链表头节点和尾节点的指针封装成一个结构体,所以想要改变这两个指针,就相当于改变这个结构体,比如要改变实参int p,那形参就传int*p(也就是接收整型变量p的地址&p),要改变实参int* p,那就传int** pp(也就是接收指针p的地址),所以现在要改变实参结构体变量stuct Name p,那么形参就传struct Name* p(也就是接收结构体变量p的地址&p),这就转化为了只需要传一级指针,而不是二级指针。

typedef int QDataType; // 链式结构:表示队列 typedef struct QListNode { struct QListNode* next; QDataType val; }QNode; // 队列的结构 typedef struct Queue { QNode* phead; QNode* ptail; int size;//存入一个数据就计数一次,方便后面计数函数的实现,同时也降低了时间复杂度 }Queue; // 初始化队列 void QueueInit(Queue* pq); // 队尾入队列 void QueuePush(Queue* pq, QDataType x); // 队头出队列 void QueuePop(Queue* pq); // 获取队列头部元素 QDataType QueueFront(Queue* pq); // 获取队列队尾元素 QDataType QueueBack(Queue* pq); // 获取队列中有效元素个数 int QueueSize(Queue* pq); // 检测队列是否为空 bool QueueEmpty(Queue* pq); // 销毁队列 void QueueDestroy(Queue* pq);

这种方法既避免了传多个参数,又避免了传二级指针!

2.2 队列的初始化

代码实现:

// 初始化队列 void QueueInit(Queue* pq) { assert(pq); pq->phead = NULL; pq->ptail = NULL; pq->size = 0; }

2.3 入队列的实现

// 队尾入队列 void QueuePush(Queue* pq, QDataType x) { assert(pq); QNode* newnode = (QNode*)malloc(sizeof(QNode));//开辟动态空间 if (newnode == NULL) { perror("malloc fail"); return; } //进行初始化 newnode->val = x; newnode->next = NULL; //进行插入 if (pq->ptail == NULL) { pq->phead = pq->ptail = newnode; } else { pq->ptail->next = newnode; pq->ptail = newnode; } pq->size++; }

2.4 出队列的实现

// 队头出队列 void QueuePop(Queue* pq) { assert(pq); assert(pq->size != 0); //一个节点的情况 if (pq->phead ->next == NULL) { free(pq->phead);//free的是指针指向的节点,而不是释放指针,注意区别 pq->phead = pq->ptail = NULL; } //多个节点的情况 else { QNode* next = pq->phead->next; free(pq->phead); pq->phead = next; } pq->size--; }

注意:这里面的free函数释放的是指针所指向的节点的空间,也就是malloc动态开辟的内存空间,而不是指针pq->phead或者pq->ptail。

2.5 队列其他功能的实现

// 获取队列头部元素 QDataType QueueFront(Queue* pq) { assert(pq); assert(pq->phead);//头节点如果为NULL,说明没有节点存入,那读取就没有意义了 return pq->phead->val; } // 获取队列队尾元素 QDataType QueueBack(Queue* pq) { assert(pq); assert(pq->ptail);//尾节点如果为NULL,说明没有节点存入,那读取就没有意义了 return pq->ptail->val; } // 获取队列中有效元素个数 int QueueSize(Queue* pq) { assert(pq); return pq->size; } // 检测队列是否为空 bool QueueEmpty(Queue* pq) { asswet(pq); return pq->size == 0; } // 销毁队列 void QueueDestroy(Queue* pq) { assert(pq); QNode* pcur = pq->phead; while (pcur) { QNode* next = pcur->next; free(pcur); pcur = next; } pq->phead = pq->ptail = NULL; pq->size=0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 11:57:24

BetterGI原神自动化工具终极指南:5大核心功能彻底解放你的双手

BetterGI原神自动化工具终极指南:5大核心功能彻底解放你的双手 【免费下载链接】better-genshin-impact 🍨BetterGI 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动派遣 | 一键强化 - UI Automation Testing T…

作者头像 李华
网站建设 2026/4/16 12:03:49

Poppler Windows:PDF处理实战完全指南

Poppler Windows版本为Windows平台用户提供了一套完整的PDF文档处理解决方案,将所有必要的依赖组件集成在一个独立的工具包中。无论您是开发者需要集成PDF功能,还是普通用户需要处理日常文档,都能获得开箱即用的专业级体验。 【免费下载链接】…

作者头像 李华
网站建设 2026/4/16 11:59:09

IwaraDownloadTool 2025完全指南:5大核心功能带你玩转Iwara视频下载

还在为无法保存喜爱的Iwara视频而苦恼吗?IwaraDownloadTool正是你需要的解决方案!这款基于TypeScript开发的浏览器扩展工具,专为Iwara视频下载而生,支持批量下载、智能链接识别、多线程下载等强大功能,让你轻松保存心仪…

作者头像 李华
网站建设 2026/4/16 0:58:12

想拥有自己的本地AI大脑?Open-AutoGLM部署教程来了,支持离线运行!

第一章:Open-AutoGLM 本地部署概述 Open-AutoGLM 是一个基于 AutoGLM 架构的开源自动化语言模型推理框架,支持在本地环境中高效部署和运行大语言模型。其设计目标是降低大模型落地的技术门槛,提供模块化、可扩展的本地服务接口,适…

作者头像 李华
网站建设 2026/4/16 13:36:25

Windows平台终极PDF处理工具:Poppler完整使用指南

Poppler for Windows为Windows用户提供了开箱即用的PDF文档处理解决方案,集成了所有必要的依赖组件,让您无需复杂的配置即可享受专业级的PDF解析和渲染能力。无论您是开发者还是普通用户,都能轻松处理各种PDF操作需求。 【免费下载链接】popp…

作者头像 李华