课程 · #3 / 11

后进先出(LIFO)——最新进来的,最先出去

Stack · LIFO

size0 top
empty stack — push to begin
init

Mini-game · balanced brackets (powered by a stack)

Type an expression. Brackets must open and close in mirror order({[…]}) is fine, ([)] is not. The parser uses a stack: every opener pushes the expected closer; every closer must match the value on top. Watch how each character is classified, and how the stack grows and shrinks below.

try
  • opener → push
  • closer matches top
  • mismatch / underflow
  • ignored char

动手试试:把令牌压(push)上塔顶;再把它们弹(pop)下来。然后在下方:往括号游戏里喂入任意带括号的字符串——那个就是解析器本身。

为什么它重要

栈无处不在:函数调用、撤销/重做、表达式解析、回溯算法。理解栈,就是理解程序如何执行,以及如何解决那些需要"记住"和"撤回"的问题。

核心思想

想想餐厅里一摞盘子。你只能从顶上拿或放。最后放上去的那只盘子,会被最先取走。

后进先出(LIFO)。

这条简单的约束威力惊人:

所有操作都是 O(1)——你永远只碰栈顶。

要点回顾

再深入一些

调用栈正是递归函数能够运作的原因——每次调用的局部变量都被压入栈中,返回时再弹出。当递归层数过深时,就会发生栈溢出。栈也是把中缀表达式转换为后缀表达式(调度场算法)以及单趟求值后缀表达式的关键。

实战中的栈

数学细节

时间复杂度
Push: O(1)
Pop: O(1)
Peek: O(1)
Search: O(n)
空间
n 个元素需 O(n)

实现

栈操作

let mut stack = Vec::new();

stack.push(1);  // Push onto top
stack.push(2);
stack.push(3);  // Stack: [1, 2, 3] (3 is top)

let top = stack.pop();  // Returns Some(3)
let peek = stack.last(); // Returns Some(&2)

经典应用

练习

三道经典的栈题目——每一道都用到了 LIFO 纪律的一种不同方式:

浏览全部练习题