当前位置: 首页 > news >正文

数据结构学习篇(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; }
http://www.cnnetsun.cn/news/184203.html

相关文章:

  • 如何在3分钟内解锁网易云音乐NCM加密文件实现音频自由?
  • 阴阳师自动化脚本2025完整使用手册:从零基础到高手进阶
  • AdGuard Home广告拦截配置完整教程:百万规则打造纯净网络
  • 2025年安卓设备VS Code终极部署手册:打造移动开发新纪元
  • springboot人口老龄化社区活动老年人服务和管理平台 _xl261auu
  • springboot四川自驾游攻略管理系统_3ra412wd
  • 网易云音乐NCM解密工具:三步解锁你的专属音乐库
  • 网盘直链下载助手终极指南:免客户端高速下载全攻略
  • 网易云音乐NCM文件终极解密:从加密到无损转换全攻略
  • Poppler Windows工具集:PDF处理效率的革命性突破
  • 5分钟彻底解锁网易云音乐NCM格式:从加密到无损的完美转换
  • iOS微信自动抢红包插件技术解析与使用指南
  • DLSS版本管理神器:DLSS Swapper完全使用指南
  • 六音音源修复版完整教程:轻松解决洛雪音乐播放问题
  • 如何快速修复洛雪音乐六音音源失效问题
  • 去论文AI痕迹别乱改!这4类句子最容易暴露,一定要重点润色
  • 知网降AI率保姆级教程:亲测有效,稳过检测!(2025最新版)
  • Vue-Office完全指南:5分钟实现Web端Office文件在线预览
  • GitHub汉化插件终极指南:5分钟让GitHub说中文
  • ncmdump终极指南:3步解锁网易云音乐NCM格式限制
  • Ollydbg下载及安装实战案例:快速搭建用户层调试器
  • 制造业数字化服务商如何助力企业转型?
  • Iwara视频下载工具完全指南:从零开始掌握高效下载技巧
  • NCM音频格式转换终极指南:轻松解锁网易云音乐加密文件
  • Anything-LLM:3分钟打造属于你的智能文档聊天机器人
  • BetterGI完整使用指南:从零开始掌握原神自动化
  • 基于Gin+Vue的前后端分离权限管理系统设计与实现
  • 参数碾压GPT-4o!HINDSIGHT重构AI Agent记忆架构,准确率提升38%!
  • DLSS Swapper终极教程:三分钟学会游戏性能优化
  • NCMconverter音频转换工具:解锁网易云音乐格式限制的实用方案