剑指Offer-05-用两个栈实现队列

题目

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

解析

预备知识

首先我们需要对栈和队列的性质了如指掌。栈和队列其实都是带有约束的线性表。
栈是一种“后进先出”的线性表,我们在线性表的尾部进行添加和删除元素。很常见的生活中的例子,就是洗盘子。我们所用过得盘子,都是最后收拾的盘子在上面,所以第一个要洗的就是第一个盘子。还有火车进站出站等等。再举个程序员都知道的例子,就是我们函数调用栈的原型也是来源栈的数据结构。其中每一次函数调用和结束都对应一次入栈和出栈的过程。每一次函数调用称为调用栈的一个栈帧,它包括操作数栈、本地变量表、动态链接和返回地址。函数A调用函数B,函数B调用函数C,函数C运行完毕,继续执行函数B,最后是函数A。
队列是一种“先进先出”的线性表,它规定只能在表头删除元素,表尾删除元素。队列的例子就更简单了,排队买车票,当然是先到先服务啊。操作系统中进程调度和页面置换调度算法都有先到先服务算法。同样线程池中的任务队列通常也是对于先到的任务优先分配线程来处理。

思路

既然有2个栈,假如我们先入队a,不妨把a推到栈1中,然后继续入队b,还是把b推到栈1中。栈1中有b,a。这时要出队一个,根据队列的性质和栈1中栈顶为b,所以无法对栈1直接pop。因为a是先进队的,要弹出的正确结果是a。这时我们的栈2还是空着呢,我们把栈1中的元素全部pop出来,并把他们推送到栈2中,这样我们a就处于栈顶了,弹出即可。假如接下来我们入队c,我们还把他加到栈1中。这时我们又要出队1个,因为栈2中的元素b比栈1中c早加进来,所以直接弹出栈2的元素即可。
总结上述思路:
1. 规定栈1为入队,栈2为出队
2. 我们规定入队操作统一加到栈1中
3. 对于出队,有2种情况。
1. 若栈2为空,则把栈1中元素全部弹出并加进栈2,然后弹出栈2的栈顶即可
2. 若栈2不为空,则直接弹出栈2栈顶即可(因为栈2的元素都比栈1的元素早)

图例

这里写图片描述

    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }

    public int pop() {
        if(stack1.isEmpty() && stack2.isEmpty()) {
            throw new RuntimeException("Queue is empty!");
        }
        if(stack2.isEmpty()) {
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

拓展

那么两个队列如何实现一个栈呢,欢迎评论区分享思路。

猜你喜欢

转载自blog.csdn.net/dawn_after_dark/article/details/80643900