用栈实现队列

70 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

重拾算法-firstday

题目: 使用两个栈实现队列,实现的队列可以支持一般队列的一系列操作,如:队列的先进先出,队尾进,队头出,(push,peek,pop,empty)

实现MyQueue类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

标准的栈的操作只有:push to toppeek/pop from topsize, 和 is empty

示例:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

栈只可以从一头进栈出栈,而队列是一头进一头出,栈其实是一种操作受限的队列,所以将两个栈合在一起形成一个队列。一个负责队列的进,一个负责队列的出。

将一组数据存入第一个栈,再从第一个栈一个一个pop,同时push进第二个栈,完成后,从第二个栈出栈,从而形成队列。

Java版代码如下:

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;
    public MyQueue() {
        stackIn = new Stack<Integer>();
        stackOut = new Stack<Integer>();
    }
    
    public void push(int x) {
        stackIn.push(x);
    }
    
    public int pop() {
        dumpStack();
        return stackOut.pop();
    }
    
    public int peek() {
        dumpStack();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }

    public void dumpStack(){
        if(!stackOut.isEmpty()) return;
        while(!stackIn.isEmpty()){
            stackOut.push(stackIn.pop());
        }
    }

代码中,使用两个栈,其中一个用来反转元素的入队的顺序,另一个存储的是元素的最终顺序,从而实现了队列的FIFO特性。

这个题目其实就像两个酒杯相互倒酒,两个酒杯看做是两个栈,把一个杯子里的酒全倒进另一个杯子,然后再倒回来,即可得到最终的顺序。