題目描述
【題目】:
編寫一個類,用兩個棧實現隊列,滿足隊列的基本操作要求:enqueue(入隊)、出隊(dequeue),peek:獲取隊列中對頭元素。
【解答】
- 棧數據結構的特點是先進後出,而隊列數據結構的特點是先進先出。用兩個棧正好能把順序反過來實現類似隊列的操作。
- 具體實現上是一個棧作爲壓入數據棧,在壓入數據棧時,只往這個棧中壓入數據(入隊),記爲 stackPush,另一個棧只作爲彈出棧,在彈出數據(出隊)只從這個棧彈出,記爲 stackPop。
- 因爲數據壓入棧的時候,順序時先進後出的。那麼只要把 stackPush 的數據再壓入 stackPop 中,順序就變回來了。
【舉個栗子】
把 1~5 依次壓入 stackPush ,那麼從stackPush 的棧頂的棧底爲 5~1 ,此時再將 5~1 倒stackPop,那麼從 stackPop 的棧頂到棧底就變成了 1~5.再從 stackPop 彈出時,順序就像隊列一樣,如圖所示:
聽起來貌似簡單,但實際上必須做到以下兩點:
1.如果 stackPush 要往 stackPop 中壓入數據,那麼必須一次性把 stackPush 中的數據全部壓入。
2.如果 stackPop 不爲空,stackPush 絕對不能向 stackPop 中壓入數據。
違反了以上兩點,都會發生錯誤。
- 違反 1 的情況舉例:1~5 依次次壓入stackPush,stackPush 的棧頂到棧底爲 5~1,從 stackPush 壓入 stackPop 時,如果只將 5 和 4 壓入了 stackPop ,stackPush 還剩下 1、2、3 沒有壓入。此時如果用戶想進行出隊操作,那麼 4 將最先彈出,與預想的隊列順序就不一致。
- 違反 2 的情況舉例:1~5 依次壓入 stackPush,將 stackPush 中的所有數據壓入了 stackPop ,此時從 stackPop 棧頂到棧底爲 1~5。此時,又有 6~10 壓入 stackPop ,這時候stackPop 不爲空不能壓入數據,如果違反2,向 stackPop 壓入數據,stackPop 棧頂到棧底爲 6~10,1~5,此時用戶如果想進行出隊操作,那麼 6 將最先彈出,又與預想的隊列順序不一致。
代碼實現
上述介紹了壓入數據的注意事項。具體實現參看如下代碼:
1public class TwoStackQueue {
2 private Stack<Integer> stackPush;
3 private Stack<Integer> stackPop;
4
5 public TwoStackQueue() {
6 stackPush = new Stack<Integer>();
7 stackPop = new Stack<Integer>();
8 }
9
10 //TODO:入隊操作,往隊列中添加數據
11 public void enqueue(int newData) {
12 this.stackPush.push(newData);
13 }
14
15 //TODO:出隊操作,從隊列中獲取數據,注意隊列數據結構是先進先出
16 public int dequeue() {
17 if (stackPush.empty() && stackPop.empty()) {
18 throw new RuntimeException("Queue is empty!");
19 } else if (stackPop.empty()) {
20 while (!stackPush.empty()) {
21 this.stackPop.push(this.stackPush.pop());
22 }
23 }
24 return stackPop.pop();
25 }
26
27 //TODO:獲取隊列中的隊頭元素
28 public int peek() {
29 if (stackPush.empty() && stackPop.empty()) {
30 throw new RuntimeException("Queue is empty!");
31 }else if (stackPop.empty()) {
32 while (!stackPush.empty()) {
33 this.stackPop.push(this.stackPush.pop());
34 }
35 }
36 return stackPop.peek();
37 }
38}
本段代碼是在在調用 dequeue 和 peek 方法時進行壓入數據的過程。這個壓入數據的操作選擇的時機可以有很多,調用 enqueue、dequeue 和 peek 三種方法中的任何一種時發生壓入數據的行爲都是可以的。只要不違反上述兩點,就不會出錯。