【數據結構】Java用兩個棧模擬實現隊列 + 用兩個隊列模擬實現棧

1.用兩個棧來實現一個隊列

要求: 完成隊列的Push和Pop操作。( 隊列中的元素爲int類型)

對於這個問題,《劍指offer》上有一張圖很形象:
在這裏插入圖片描述
在圖中可以看出它用stack1來模擬入隊列,用stack2來模擬出隊列。然後注意兩點就可以很容易的完成這個問題:

  • 1.push( )操作,直接將數據壓入stack1即可;
  • 2.pop( )操作,將stack1中的數據彈出然後再壓入到stack2中,這樣數據在兩個棧中順序就相反了,這樣就保證了stack2()棧頂元素一直是最先進隊列的元素,爲保證最先進入的數據一直處於棧頂,只有將stack2中的數據全部pop後,才能繼續講stack1中的數據壓入到stack2中,繼續做pop()。

代碼:

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);  //入隊列,直接將數據壓入stack1()中
    }
    
    public int pop() {
        if(stack2.empty()) {    //stack2棧頂一直是最先進入隊列的元素,爲保證出隊列時它能第一個出,所以它只要不爲空,stack1中的元素就得老實待着,不能彈出到stack2中。
            while(!stack1.empty()) {        //stack2空了之後,stack1棧底元素就成了最先進入隊列的元素,此時就可以將stack1中的數據全部彈出到stack2中。這樣stack2的棧頂元素又是最先進入隊列的元素了。
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();  //由於有了上面前提,stack2棧頂元素,一直都是最先進入隊列的元素。
    }
}

2.用兩個隊列來實現一個棧

題目鏈接:LeetCode 225

要求實現以下功能:

  • push(x) – 元素 x 入棧
  • pop() – 移除棧頂元素
  • top() – 獲取棧頂元素
  • empty() – 返回棧是否爲空

做法:

  • 入棧:類似於上面用棧實現隊列,這裏直接把數據入q1;
  • 出棧:模擬出棧操作大概可以分三步:
    第一步:將q1中的元素留一個,剩下的全部出隊,進入q2。 留一個是因爲,出棧順序是先入後出,先把它之前的所有元素搬走,再將它出隊列,就完成了出棧操作;
    第二步:將q1中剩下的最後一個元素出隊列,就完了出棧操作。 (因爲他就是最後一個進入棧的元素);
    第三步:交換q1,q2。 前面已經可以完成出棧操作,爲什麼還會有這個第三步呢?因爲爲了省事,如果不交換,每次都要再出棧都要判斷兩個隊列哪個不爲空。很麻煩。

代碼:

class MyStack {
    private Queue<Integer> q1;
    private Queue<Integer> q2;
    
    /** Initialize your data structure here. */
    public MyStack() {
        q1 = new LinkedList<>();
        q2 = new LinkedList<>();   //在構造函數裏給兩個隊列初始化
    }
    
    
    /** Push element x onto stack. */
    public void push(int x) {
        q1.offer(x);     //入棧就直接把元素放進q1
    }
    
    
    /** Removes the element on top of the stack and returns that element. */
    //模擬出棧操作大概可以分三步:
    //第一步:將q1中的元素留一個,剩下的全部出隊,進入q2。   留一個是因爲,出棧順序是先入後出,先把它之前的所有元素搬走,再將它出隊列,就完成了出棧操作。
    //第二步:將q1中剩下的最後一個元素出隊列,就完了出棧操作。  (因爲他就是最後一個進入棧的元素)
    //第三步:交換q1,q2。      前面已經可以完成出棧操作,爲什麼還會有這個第三步呢?因爲爲了省事,如果不交換,每次都要再出棧都要判斷兩個隊列哪個不爲空。很麻煩。
    public int pop() { 
        while(q1.size()>1) {       //第一步:q1隊尾留下,剩下的全部進入q2
            q2.offer(q1.poll()); 
        }
        int ret = q1.poll();     //第二步:將剛剛那個留下的隊尾元素出隊。
        Queue<Integer> temp = q1;
        q1 = q2;
        q2 = temp;         //第三步:交換q1,q2
        return ret;        
    }
    


    /** Get the top element. */
    //獲取棧頂元素
    public int top() {
       //第一步將q1中size-1個元素搬移到q2中
        while(q1.size()>1) {
            q2.offer(q1.poll()); 
        }
        //獲取q1隊頭元素
        int ret = q1.peek();
        //將其搬運到q2
        q2.offer(q1.poll());
        //第三步交換q1,q2,不交換的話話在插的時候就需要考慮哪個隊列不爲空插哪個很麻煩,直接暴力一點,交換省事。
        Queue<Integer> temp = q1;
        q1 = q2;
        q2 = temp;
        return ret;
    }
    


    /** Returns whether the stack is empty. */
    public boolean empty() {
        return q1.isEmpty();
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章