1. 程式人生 > >棧實現佇列,用兩個棧實現佇列方法詳解(含實現程式碼)

棧實現佇列,用兩個棧實現佇列方法詳解(含實現程式碼)

棧怎樣才能實現和佇列一樣從棧的底層抽出元素呢?一般會用兩個棧來實現佇列。

首先,我們將兩個棧分別定義為 stack1 與 stack2。

實現方案 1

我們讓入隊操作在 stack1 中執行,而出隊操作在 stack2 中執行。執行方式如下。
  • 入隊:直接向 stack1 中入棧。
  • 出隊:將 stack1 中的所有元素出棧,依次入棧到 stack2 中,然後彈出 stack2 中的棧頂元素,接著把 stack2 中的所有元素出棧,依次壓入 stack1 中。

為了便於理解,我們藉助圖 1 解釋上述入隊操作。


圖 1 入隊操作
出隊操作如圖 2 所示。


圖 2 出隊操作
來回入隊、出隊比較煩瑣,尤其是出隊比較麻煩,需要先將元素從 stack1 倒入 stack2 裡,然後在 stack2 彈出元素之後又倒回到 stack1 裡。有沒有更好的辦法呢?當然有,方案 2 就是改進之後的思路。

實現方案 2

入隊都在 stack1 中進行,stack2 用於出隊,同時保證所有元素都在一個棧裡,且遵守以下規則。
  • 入隊:不管 stack1 是否為空棧,都將 stack2 中的所有元素壓入 stack1 中。
  • 出隊:若 stack2 不為空棧,則直接從 stack2 中彈出元素;若 stack2 為空棧,則把 stack1 中的元素倒入 stack2 中,再從 stack2 中彈出元素;若兩個棧都是空的,則說明佇列為空隊,不能出隊。這與方案 1 的思路一樣,只不過把倒回去的這個操作放到了入隊時執行,卻使連續入隊、出隊的效率提高了。

還有更好的辦法嗎?當然有。方案 3 就是一種更優的解決辦法。

實現方案 3

入隊都在 stack1 中進行,出隊在 stack2 中進行,同時遵守以下規則。
  • 入隊:直接把元素壓入 stack1 中。
  • 出隊:如果 stack2 不為空,則直接彈出 stack2 中的元素;如果 stack2 為空,則將 stack1 中的所有元素倒入 stack2 中,然後彈出 stack2 中的棧頂元素。同樣,若兩個棧都為空棧,則佇列為空隊,無法出隊。

這個方案在入隊時非常簡單,而在出隊時,多數情況下可以直接通過出隊 stack2 實現,若需要把 stack1 中的元素倒入 stack2 中,則一般不用每次都進行這樣操作。最壞的情況就是出隊一個元素、入隊一個元素這樣的迴圈操作,導致每次出隊都要轉移元素。

其實這三種方案的操作是一樣的。總體來說,方案 3 是非常好的方案。

下面為方案 3 的程式碼實現。
package me.irfen.algorithm.ch02.extend;
import me.irfen.algorithm.ch02.Stack;
public class Stack2Queue {
    private Stack stack1;
    private Stack stack2;
    private int maxLength;

    public Stack2Queue(int capacity) {
        maxLength = capacity;
        stack1 = new Stack(capacity);
        stack2 = new Stack(capacity);
    }

    public boolean put(int item) {
        if (stack1.isFull() || maxLength == size()) {
            // 滿了
            return false;
        }
        stack1.push(item);
        return true;
    }

    public int poll() {
        if (!stack2.isEmpty()) {
            return stack2.pop();
        } else {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
            return stack2.pop();
        }
    }

    public int size() {
        return stack1.size() + stack2.size();
    }
}
下面是測試程式碼:
package me.irfen.algorithm.ch02.extend;
public class Stack2QueueTest {
    public static void main(String[] args) {
        Stack2Queue queue = new Stack2Queue(5);
    queue.put(1);
    queue.put(2);
    System.out.println(queue.poll()); // 1
    queue.put(3);
    queue.put(4);
    System.out.println(queue.poll()); // 2
    System.out.println(queue.poll()); // 3,本次會把3、4兩個元素從stack1倒入stack2
}
}