[Day10]栈与队列

82 阅读3分钟

今日内容:栈与队列理论基础、232.用栈实现队列、225.用队列实现栈 代码随想录链接:代码随想录 (programmercarl.com)

232.用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty): 实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false 说明:
  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

用栈实现队列的话,用一个栈作为进栈,然后再按顺序出栈并进栈到另一个栈,就可以实现输出顺序的反转,此时只需要保证进栈元素转换到出栈室,出栈是空的,即可实现队列的作用。

因此可以写出将进栈元素转换到出栈的函数:

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

全部代码如下:

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;
    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();
    }
    
    public void push(int x) {
        stackIn.push(x);

    }
    
    public int pop() {
        swith();
        return stackOut.pop();
    }
    
    public int peek() {
        swith();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }
    private void swith(){
        if(!stackOut.isEmpty()) return;
        while (!stackIn.isEmpty()){
            stackOut.push(stackIn.pop());
        }
    }
}

225.用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。 实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 注意:
  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

想了一下,需要一个操作将顺序弄成栈的顺序,这个操作放在入栈或者出栈都可以。

放在入栈的话,先把元素放在辅助的队列,当主队列非空的时候,将主队列元素逐个poll出然后offer到辅助队列,再通过转换将辅助队列换成主队列。就可以让存在队列中的元素是符合栈的顺序的。

出栈的话,需要将一个队列的前n-1个元素全部导入到另一个队列中,然后输出剩下的那个一个元素。下面代码将这个操作放在入栈:

class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
        queue2.offer(x); // 先放在辅助队列中
        while (!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }
        Queue<Integer> queueTemp;
        queueTemp = queue1;
        queue1 = queue2;
        queue2 = queueTemp;
    }
    
    public int pop() {
        return queue1.poll();
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.isEmpty();
    }
}

这个操作也可以用一个队列完成,就是将输出的元素重新输入回开头,刚好可以把最后一个元素输出去:

class MyStack {

    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<>();
    }

    //每 offer 一个数(A)进来,都重新排列,把这个数(A)放到队列的队首
    public void push(int x) {
        queue.offer(x);
        int size = queue.size();
        //移动除了 A 的其它数
        while (size-- > 1)
            queue.offer(queue.poll());
    }

    public int pop() {
        return queue.poll();
    }

    public int top() {
        return queue.peek();
    }

    public boolean empty() {
        return queue.isEmpty();
    }
}

结束。