Semorphe

佇列與堆疊

兩個只差在「從哪一端拿」的容器。 · ⏱ 約 30 分鐘

你會學到三件事

  1. queue 先進先出、stack 後進先出
  2. 它們故意不讓你看中間
  3. 遞迴其實就是一個你看不見的 stack

開始之前

vector 什麼都能做——那為什麼還要這兩個?

因為限制本身是有價值的。看完這一課再回來想這句話。

一、兩個,一眼看完

queue<int> q;                  stack<int> st;
q.push(1);                     st.push(1);
q.push(2);                     st.push(2);
cout << q.front();  // 1       cout << st.top();  // 2
q.pop();                       st.pop();
cout << q.front();  // 2       cout << st.top();  // 1
從哪裡進 從哪裡出 叫什麼
queue 後面 前面 先進先出(FIFO)——排隊
stack 上面 上面 後進先出(LIFO)——疊盤子

⚠️ 名字不一樣queuefront()stacktop()

⚠️ pop() 不回傳值——它只是拿掉。要值得先 front() / top()

⚠️ 空的時候呼叫 front() / top() 是未定義行為,不會報錯。 用之前先 if (!q.empty())

二、🔴 它們故意不讓你看中間

q[3] 是不合法的。這不是缺功能,是設計。

一個限制得剛好的工具,讓錯誤的用法寫不出來。

vector 模擬佇列的話,你可以不小心從中間拿東西—— 而那多半是一個 bug。queue 讓那個 bug 連編譯都過不了。

所以判準是:你的演算法只從兩端動嗎? 是 → 用專門的那個。

三、它們各自在哪裡出現

用在什麼
queue BFS(第 11 課)、模擬排隊、生產者消費者
stack DFS、括號配對、運算式求值、回溯

四、🔴 遞迴就是一個看不見的 stack

C++ 入門第 16 課的階乘:

f(5) → f(4) → f(3) → f(2) → f(1)
                                 ↓ 回來
                        ← ← ← ← ←

那個「回來」的順序是後進先出——最後被叫的最先回來。

電腦就是用一個 stack 存這些「還沒回來的呼叫」,那叫呼叫堆疊

⚠️ 所以「遞迴太深會 stack overflow」是字面意思:那個 stack 滿了。

而反過來:任何遞迴都可以改寫成用一個 stack 的迴圈。 遞迴太深時就是這樣改的。

完成的樣子

int main() {
    queue<int> q;
    q.push(1);
    q.push(2);
    cout << q.front() << endl;
    q.pop();
    cout << q.front() << endl;
    stack<int> st;
    st.push(1);
    st.push(2);
    cout << st.top() << endl;
    return 0;
}

下一課

queuestack標準函式庫給你的。下一課要自己做一個 ——那是 Linked List,而它也是後面「圖」和「樹」的地基。

換你了

stack 判斷一串括號有沒有配對好:"(())" ✅、"(()" ❌。

提示:遇到 ( 就 push,遇到 ) 就 pop。 ⚠️ 兩個地方要小心:pop 之前 stack 空了(右括號太多), 以及最後 stack 沒空(左括號太多)。

這一課你做了什麼

如果卡住了

你看到 多半是因為
q.top() 編譯錯誤 queue 用 front()
pop() 拿不到值 它不回傳。要先 front()/top()
程式當掉 對空的容器呼叫了 front()/top()
順序反了 弄混了 FIFO 和 LIFO
在編輯器打開這一課 →