【算法】用两个栈实现队列

101 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

题目

用两个栈实现一个队列。队列声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的能力。

解题思路

栈的特点都知道是"先进后出",题目要求是实现尾部插入和头部删除能力。因此需要解决如何用两个栈来实现一个"先进先出"队列功能。

举例分析队列插入和删除的过程:

删除的操作

  1. 先向stack1插入元素a,b,c,stack1中元素:{a,b,c}
  2. 若要对元素做删除操作,删除头部元素a。栈是"先进后出",a元素在栈的栈底。
  3. 将stack1中的元素依次弹出压入stack2,stack2中元素:{c,b,a}
  4. 弹出stack2栈顶元素就删除了元素a

插入的操作

  1. 若要插入元素,若之前是做过删除操作就需要将stack2中的元素都压入到stack1中保证元素排序是正向。
  2. 然后再向stack1中插入新元素即可。
  3. 如果元素都在stack1中了,直接插入新元素。
    Deque<Integer> stack1; // +队列
    Deque<Integer> stack2; // -队列

    public CQueue() {
        stack1 = new ArrayDeque<Integer>();
        stack2 = new ArrayDeque<Integer>();
    }

    public void appendTail(int value) {
        stack1.push(value); // 添加
    }

    public int deleteHead() {
        if (stack2.isEmpty()) {
            if (stack1.isEmpty()) {
                return -1;
            }
            in2out(); // 转移
        }
        return stack2.pop(); // 删除
    }

    private void in2out() {
        while (!stack1.isEmpty()) {
            stack2.push(stack1.pop()); 
        }
    }

PS: deque容器为一个给定类型的元素进行线性处理,像向量一样,它能够快速地随机访问任一个元素,并且能够高效地插入和删除容器的尾部元素。但它又与vector不同,deque支持高效插入和删除容器的头部元素,因此也叫做双端队列。

总结

其实再想象一下两个栈是镜像的两个桶,输入都是往stack1进行,删除都是在stack2进行。

当需要进行添加操作时,将元素都移动到stack1中做添加操作;当需要进行删除操作时,将元素都移动到stack2中做删除操作。

image.png