棧實現佇列,用兩個棧實現佇列方法詳解(含實現程式碼)
阿新 • • 發佈:2018-12-23
棧怎樣才能實現和佇列一樣從棧的底層抽出元素呢?一般會用兩個棧來實現佇列。
首先,我們將兩個棧分別定義為 stack1 與 stack2。
為了便於理解,我們藉助圖 1 解釋上述入隊操作。
圖 1 入隊操作
出隊操作如圖 2 所示。
圖 2 出隊操作
來回入隊、出隊比較煩瑣,尤其是出隊比較麻煩,需要先將元素從 stack1 倒入 stack2 裡,然後在 stack2 彈出元素之後又倒回到 stack1 裡。有沒有更好的辦法呢?當然有,方案 2 就是改進之後的思路。
入隊都在 stack1 中進行,stack2 用於出隊,同時保證所有元素都在一個棧裡,且遵守以下規則。
還有更好的辦法嗎?當然有。方案 3 就是一種更優的解決辦法。
入隊都在 stack1 中進行,出隊在 stack2 中進行,同時遵守以下規則。
這個方案在入隊時非常簡單,而在出隊時,多數情況下可以直接通過出隊 stack2 實現,若需要把 stack1 中的元素倒入 stack2 中,則一般不用每次都進行這樣操作。最壞的情況就是出隊一個元素、入隊一個元素這樣的迴圈操作,導致每次出隊都要轉移元素。
其實這三種方案的操作是一樣的。總體來說,方案 3 是非常好的方案。
下面為方案 3 的程式碼實現。
下面是測試程式碼:
首先,我們將兩個棧分別定義為 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 不為空棧,則直接從 stack2 中彈出元素;若 stack2 為空棧,則把 stack1 中的元素倒入 stack2 中,再從 stack2 中彈出元素;若兩個棧都是空的,則說明佇列為空隊,不能出隊。這與方案 1 的思路一樣,只不過把倒回去的這個操作放到了入隊時執行,卻使連續入隊、出隊的效率提高了。
還有更好的辦法嗎?當然有。方案 3 就是一種更優的解決辦法。
實現方案 3
- 入隊:直接把元素壓入 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 } }