大家好!今天我们来学习一种非常有用的数据结构——队列(Queue)。
想象一下我们在排队买票或者等公交车,是不是遵守“先来的人先服务”的规则?队列就是这样一种遵循 "先进先出"(FIFO, First In First Out) 原则的线性数据结构。
在 C++ 中,我们可以方便地使用标准库提供的 <queue>
头文件中的 queue
容器适配器来实现队列。它封装了底层容器(默认是 deque
),并提供了队列的标准操作。
push(element)
:将一个新元素添加到队尾。pop()
:移除队头的元素(注意:不返回元素值)。front()
:返回队头元素的引用(不移除)。对空队列调用是未定义行为!back()
:返回队尾元素的引用(不移除)。对空队列调用是未定义行为!empty()
:检查队列是否为空,是则返回 true
,否则返回 false
。size()
:返回队列中当前元素的数量。使用普通数组实现队列时,随着入队和出队操作,可能会出现数组前面有很多空位,但队尾指针已经到达数组末端,导致无法再入队,这就是“假溢出”。
循环队列 通过将数组看作一个环形空间来解决这个问题。当指针到达数组末尾时,它可以“绕回”到数组的开头。
实现循环队列的关键在于使用取模运算(%
)来更新头尾指针,并需要判断队列是空还是满。
deque
(发音类似 "deck") 是一种更强大的序列容器,它允许在 两端 进行高效的插入和删除操作。
虽然 queue
默认使用 deque
作为底层容器,但 deque
本身提供了更丰富的功能。
队列的 FIFO 特性使其非常适合处理需要按顺序处理的任务或数据。
问题:给定一个数组和一个固定大小的窗口 k,窗口从左到右滑动,每次滑动一步,求出每个窗口内的最大值。
思路: 使用一个双端队列 (deque) 来维护一个单调递减的索引序列。队头始终是当前窗口最大值的索引。
BFS 是一种用于遍历或搜索树或图的算法。它从根节点(或任意选定的起始节点)开始,探索邻近节点,然后再扩展到下一层级的节点。队列是实现 BFS 的核心工具。
BFS 过程:
应用场景: 寻找无权图的最短路径、层序遍历、查找连通分量等。
编写一个 C++ 函数,接收一个 queue<int>
作为参数,将其元素顺序反转。你可以使用栈 (stack
) 作为辅助数据结构,但不能使用另一个队列。
请尝试使用 两个 queue
来实现一个栈。你需要实现栈的基本操作:push(x)
, pop()
(移除栈顶元素), top()
(返回栈顶元素), 和 empty()
。
今天我们学习了队列(Queue)这种重要的数据结构,掌握了它的核心特性和操作:
push
, pop
, front
, back
, empty
, size
(以 queue
为例)。deque
) 的两端操作能力。front()
, back()
, 或 pop()
之前,务必使用 empty()
检查队列是否为空,避免程序出错。pop()
不返回值: queue::pop()
只负责移除队头元素,如果需要获取该元素的值,应先调用 front()
。queue
(FIFO), priority_queue
(优先出队), deque
(双端操作)。根据具体需求选择最合适的。queue
(默认基于deque
)和deque
的两端操作通常是 O(1) 均摊时间复杂度,但在某些实现或极端情况下可能涉及内存重新分配。希望大家课后多多练习,熟练掌握队列的使用!