数据结构|队列
完成阅读您将会了解队列的:
- 概念
- 构建方法
- 基本操作
- C++实现
- Rust实现
1. 概念
队列(Queue)是一种抽象数据类型,遵循先进先出(First-In-First-Out, FIFO)原则,双端开放的线性表,如图1[1]。队列可以辅助完成广度优先搜索(Breadth First Search)算法的实现。此外,队列有一个常用的变体,优先队列(Priority Queue)。优先队列属于二叉堆(Binary Heap)的一个应用,具体内容请参考数据结构堆。

2. 构建方法
数组和双链表都可以作为构建队列的基础容器。用数组构建队列时可以采用循环队列(Circular Queue),提高空间利用率。
3. 基本操作
| 操作 | 描述 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|
| PUSH(value) | 队尾入队 | \(\Theta(1)\) | \(\Theta(1)\) |
| POP() | 队头出队 | \(\Theta(1)\) | \(\Theta(1)\) |
4. C++实现
template <class T> struct Node {
T val;
Node *before, *after;
Node(auto val) : val(val), before(nullptr), after(nullptr) {}
Node() : Node(0) {}
};
template <class T> class Queue {
Node<T> *head, *tail;
size_t len;
public:
Queue() : head(nullptr), tail(nullptr), len(0) {}
~Queue() {
while (head) {
auto garbage = head;
head = head->after;
delete garbage;
}
}
constexpr auto front() const { return head->val; }
inline void pop() noexcept {
if (head) {
auto garbage = head;
head = head->after;
delete garbage;
garbage = nullptr;
--len;
}
}
inline void push(auto val) noexcept {
auto new_node = new Node(val);
head ? (new_node->before = tail, tail->after = new_node) : head = new_node;
tail = new_node;
++len;
}
constexpr auto empty() const noexcept { return len == 0; }
constexpr auto size() const noexcept { return len; }
};
此外,C++标准库提供了队列queue与双端队列deque直接使用。
5. Rust实现
impl<T> Queue<T> {
#[inline]
pub fn new() -> Self { Self { head: None, tail: None, size: 0 } }
#[inline]
pub fn front(&self) -> Option<&T> {
self.head.as_ref().map(|node| unsafe { &node.as_ref().val })
}
#[inline]
fn pop(&mut self) {
if let Some(node) = self.head.take() {
unsafe {
let node = Box::from_raw(node.as_ptr());
self.head = node.after;
match self.head {
None => self.tail = None,
Some(head) => (*head.as_ptr()).before = None,
}
}
self.size -= 1;
}
}
#[inline]
fn push(&mut self, val: T) {
let node = Some(Box::leak(Box::new(Node { after: None, before: self.tail, val })).into());
match self.tail {
None => self.head = node,
Some(tail) => unsafe { (*tail.as_ptr()).after = node },
}
self.tail = node;
self.size += 1;
}
#[inline]
pub fn empty(&self) -> bool { self.size == 0 }
#[inline]
pub fn len(&self) -> usize { self.size }
}
unsafe impl<#[may_dangle] T>Drop for Queue<T> {
fn drop(&mut self) {
struct DropGuard<'a, T>(&'a mut Queue<T>);
impl<'a,T>Drop for DropGuard<'a,T>{
#[inline]
fn drop(&mut self){ while !self.0.empty(){} }
}
while let Some(node)=self.head{
let guard=DropGuard(self);
drop(node);
mem::forget(guard);
self.head=unsafe{(*node.as_ptr()).after};
}
}
}
struct Queue<T> {
head: Option<NonNull<Node<T>>>,
tail: Option<NonNull<Node<T>>>,
size: usize,
}
struct Node<T> {
val: T,
before: Option<NonNull<Node<T>>>,
after: Option<NonNull<Node<T>>>,
}
此外,Rust标准库提供了双端队列VecDeque直接使用。
6. 自我测试
伪代码实践:
N/A
LeetCode选荐:
- Number of Recent Calls
- Design Circular Queue
- Design Circular Deque
- Sliding Window Maximum
- Shortest Subarray with Sum at Least K
让每一天足够精致,期待与您的再次相遇! ^_^

浙公网安备 33010602011771号