Skip to content

双端队列

本节学习双端队列,也就是 deque。

双端队列允许在两端插入和删除元素。它比普通队列更灵活,既可以模拟栈,也可以模拟队列,还常用于一些滑动窗口类问题。


普通队列只能从队尾入队、从队头出队。双端队列则允许两端都进行插入和删除。

左端 右端
↓ ↓
A <-> B <-> C <-> D

双端队列通常支持:

  • 从左端插入。
  • 从右端插入。
  • 从左端删除。
  • 从右端删除。
  • 查看左端元素。
  • 查看右端元素。

因为两端都能操作,所以它的使用范围比普通队列更广。


如果只从同一端插入和删除,双端队列就可以模拟栈。

deque<int> values;
values.push_back(10);
values.push_back(20);
int top = values.back();
values.pop_back();

这里所有元素都从右端进入,也从右端离开,因此符合后进先出规则。


如果从一端插入、另一端删除,双端队列就可以模拟普通队列。

deque<int> values;
values.push_back(10);
values.push_back(20);
int first = values.front();
values.pop_front();

这里元素从右端进入,从左端离开,因此符合先进先出规则。


双端队列适合需要灵活处理两端元素的场景。

例如:

  • 需要同时支持头部和尾部插入删除。
  • 需要模拟栈或队列。
  • 滑动窗口中需要维护窗口两端。
  • 某些算法中需要从两端选择候选元素。

在 Python 中,collections.deque 是常用的双端队列结构。在 Java 中,ArrayDeque 经常用于栈和队列。在 C++ 中,deque 是标准库容器之一。C# 标准库没有直接同名的 Deque,简单场景可用 QueueStackLinkedList 根据需求替代。


双端队列不是随便替代所有结构

Section titled “双端队列不是随便替代所有结构”

双端队列很灵活,但并不意味着它永远优于栈和队列。

如果问题只需要后进先出,使用栈能让意图更清晰。如果问题只需要先进先出,使用队列也更直接。双端队列适合两端都可能操作的场景,而不是为了“功能更多”就到处使用。


双端队列允许在两端插入和删除元素,因此可以模拟栈,也可以模拟队列。

它的优势是灵活,适合两端都需要操作的场景。选择时仍然要看问题本身的规则:只需要后进先出就用栈,只需要先进先出就用队列,两端都需要操作时再考虑双端队列。