Skip to content

栈与队列的对比和选择

本节总结栈、队列和双端队列之间的区别。

学习完成后,你需要能够根据问题中的处理顺序选择合适结构:最近的先处理,通常用栈;最早的先处理,通常用队列;两端都需要灵活操作,可以考虑双端队列。


栈和队列最大的区别是元素离开的顺序不同。

栈: 后进先出
队列:先进先出

假设元素进入顺序都是 A、B、C。

栈的离开顺序是:

C -> B -> A

队列的离开顺序是:

A -> B -> C

这一个差异,会直接改变整个算法或程序流程。


当问题具有下面特征时,可以优先考虑栈:

  • 需要处理最近出现的元素。
  • 需要撤销最近一次操作。
  • 需要回退到上一个状态。
  • 需要匹配最近的未完成结构。
  • 需要反向恢复某个过程。

典型场景包括括号匹配、函数调用、浏览器后退、编辑器撤销、表达式求值等。

栈强调的是“最近优先”。


当问题具有下面特征时,可以优先考虑队列:

  • 需要按照到达顺序处理。
  • 先来的任务应该先执行。
  • 数据需要排队等待。
  • 需要一层一层扩展。
  • 需要保持原始顺序。

典型场景包括打印队列、任务调度、消息缓冲、请求处理、广度优先搜索等。

队列强调的是“先来先处理”。


当问题不仅需要处理一端,还需要根据情况操作两端时,可以考虑双端队列。

例如,某些滑动窗口问题中,窗口左端会随着范围移动而删除元素,右端会随着新元素加入而插入元素。还有一些问题需要同时从两端取候选值,这时双端队列会比普通栈或普通队列更合适。

双端队列强调的是“两端灵活操作”。


可以用下面的方式快速记忆:

结构 插入位置 删除位置 规则
栈 栈顶 栈顶 后进先出
队列 队尾 队头 先进先出
双端队列 两端 两端 两端可操作

这张表不只是记忆用的。真正做题或设计程序时,你可以先判断数据应该从哪里进入、从哪里离开,再决定使用哪种结构。


一个常见误区是:看到线性数据就直接使用数组或列表。

实际上,如果问题的操作顺序很明确,使用栈或队列能让代码意图更清楚。比如括号匹配用普通列表也能写,但本质上是在把列表当栈使用。任务排队也可以用列表保存,但本质上是在表达队列规则。

另一个误区是:觉得双端队列功能更多,所以总是优先使用双端队列。功能更多不一定代表模型更清晰。结构选择应该服务于问题规则,而不是只看容器功能数量。


本章从受限线性表出发,学习了栈、队列、循环队列和双端队列。

栈适合处理最近优先的问题,队列适合处理先来先服务的问题,循环队列展示了队列的一种数组实现优化方式,双端队列则提供了两端都能操作的灵活模型。


选择栈还是队列,关键是看元素的处理顺序。

如果最近进入的元素应该最先离开,就使用栈。如果最早进入的元素应该最先离开,就使用队列。如果两端都需要插入和删除,就考虑双端队列。理解这些规则后,很多算法流程都会变得更容易建模。