1. 程式人生 > 其它 >1.佇列實現棧以及棧實現佇列

1.佇列實現棧以及棧實現佇列

佇列實現棧以及棧實現佇列

佇列和棧就是操作受限的資料結構

因為佇列和棧底層就是陣列和連結串列封裝的,只暴露頭尾操作的API。

佇列主要在BFS演算法,棧主要用在括號相關的問題

佇列:先進先出

棧:先進後出

用棧實現佇列

呼叫 push 入隊時,只要把元素壓縮S1即可,peek檢視隊頭時,當S2為空時,可以把S1所有元素取出再新增進S2,這時就是先進先出順序

同理,對於pop操作,只要操作S2既可以

如果兩個棧都為空,說明佇列為空

peek 操作,調⽤它時可能觸發 while 循 環,這樣的話時間複雜度是 O(N),但是⼤部分情況下 while 迴圈不會被觸發,時間複雜度是 O(1)。

由於pop 操作調⽤了 peek,它的時間複雜度和 peek 相同。 像這種情況,可以說它們的最壞時間複雜度是 O(N),因為包含 while 迴圈,可能需要從 s1 往 s2 搬移元 素。

但是它們的均攤時間複雜度是 O(1),這個要這麼理解:對於⼀個元素,最多隻可能被搬運⼀次,也就是說peek 操作平均到每個元素的時間複雜度是 O(1)。

class MyQueue {
    private Stack<Integer> s1,s2;
    public MyQueue() {
        s1 = new Stack<>();
        s2 = new Stack<>();
    }
    
    public void push(int x) {//新增元素到隊尾
        s1.push(x);
    }
    
    public int pop() {//刪除隊頭的元素並返回
        peek();//先呼叫peek保證s2非空
        return s2.pop();
    }
    
    public int peek() {//返回隊頭元素
        if(s2.isEmpty()){
            while(!s1.isEmpty()){//s1不是空的
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }
    
    public boolean empty() {//判斷佇列是否為空
        return s1.isEmpty() && s2.isEmpty();
    }
}

用佇列實現棧

⽤佇列實現棧就⽐較簡單粗暴了,只需要⼀個佇列作為底層資料結構

class MyStack {
    Queue<Integer> q = new LinkedList<>();
    int top_elem = 0;

    public MyStack() {

    }
    
    public void push(int x) {//新增元素到棧頂
        q.offer(x);
        top_elem = x;//隊尾為棧頂
    }
    
    public int pop() {//刪除棧頂元素並返回
        int size = q.size();
        while(size >2){//留下隊尾2個元素
            q.offer(q.poll());
            size--;
        }
        top_elem = q.peek();//記錄新的隊尾元素
        q.offer(q.poll());
        return q.poll();//刪除之前的隊尾元素
    }
    
    public int top() {//返回棧頂元素
        return top_elem;
    }
    
    public boolean empty() {//判斷棧是否為空
        return q.isEmpty();
    }
}