cover

視覺化概覽

graph TD
    PUSH["push(40)"] -.-> TOP
    TOP["頂端 → 30"] --> MID["20"] --> BOT["10"]
    TOP2["頂端 → 40"] --> E30["30"] --> E20["20"] --> E10["10"]
    POP["pop() = 40"] -.-> TOP2
    subgraph 操作前
        TOP
        MID
        BOT
    end
    subgraph 操作後
        TOP2
        E30
        E20
        E10
    end
    style PUSH fill:#9f9,stroke:#333
    style POP fill:#f99,stroke:#333

💡 白話版:Stack 就像一疊盤子。最後放上去的最先拿走(LIFO)。你瀏覽器的「上一頁」就是用 Stack 做的。

什麼是堆疊?

堆疊就像一疊盤子,只能從最上面放、從最上面拿。

後進先出 (LIFO - Last In First Out)

      ┌────┐
      │ 30 │  ← top(最後放的,最先拿)
      ├────┤
      │ 20 │
      ├────┤
      │ 10 │  ← bottom(最先放的,最後拿)
      └────┘

核心操作

操作說明時間
push(x)放入元素到頂端O(1)
pop()取出頂端元素O(1)
peek()查看頂端(不取出)O(1)
isEmpty()是否為空O(1)

所有操作都是 O(1)!

Push 操作

push(40):

      ┌────┐
      │ 30 │  top            ┌────┐
      ├────┤          →      │ 40 │  ← 新的 top
      │ 20 │                 ├────┤
      ├────┤                 │ 30 │
      │ 10 │                 ├────┤
      └────┘                 │ 20 │
                             ├────┤
                             │ 10 │
                             └────┘

Pop 操作

pop() = 30:

      ┌────┐
      │ 30 │  ← 取出          ┌────┐
      ├────┤          →      │ 20 │  ← 新的 top
      │ 20 │                 ├────┤
      ├────┤                 │ 10 │
      │ 10 │                 └────┘
      └────┘

實作方式

用 Array 實作

class Stack {
    Object[] data;
    int top = 0;  // 指向下一個要放的位置
 
    void push(x) { data[top++] = x; }
    Object pop() { return data[--top]; }
}

用 Linked List 實作

class Stack {
    Node head;  // 頭就是 top
 
    void push(x) { addFirst(x); }
    Object pop() { return removeFirst(); }
}

經典應用

1. 括號匹配

輸入: {[()]}
過程:
  { → push('{')      stack: ['{']
  [ → push('[')      stack: ['{', '[']
  ( → push('(')      stack: ['{', '[', '(']
  ) → pop() = '('    stack: ['{', '[']     ✓ 匹配
  ] → pop() = '['    stack: ['{']          ✓ 匹配
  } → pop() = '{'    stack: []             ✓ 匹配
結果: stack 為空 → 匹配成功!

2. 瀏覽器上一頁/下一頁

瀏覽: A → B → C
back stack: [A, B, C]  ← 目前在 C

按「上一頁」:
  pop() = C → 存到 forward stack
  peek() = B → 顯示 B

3. 撤銷操作 (Undo)

每次操作 push 到 stack,Undo 就 pop。

4. 函數呼叫堆疊 (Call Stack)

void a() { b(); }
void b() { c(); }
void c() { ... }
 
Call Stack:
  c()  ← 目前執行
  b()
  a()
  main()

什麼時候用 Stack?

  • 需要「最後處理的先完成」的場景
  • 遞迴改迭代
  • 深度優先搜尋 (DFS)
  • 表達式求值

相關檔案