【数据结构】栈与队列 | 互相实现

210 阅读3分钟

java中的栈与队列

java中的栈实现

从java1.0开始,标准类库中包含了Stack类。但是Stack类扩展了Vector类,使得操作者可以利用insert和remove在任意位置添加和删除栈元素,而不只是在栈顶,这种非栈操作不是很完美。
java.util.Stack<E>

  • E push(E element):将element压入栈,并返回element
  • E pop()将element出栈,并返回element,不能非法操作
  • E peek() 返回栈顶元素,但不出栈,不能非法操作

问题:Stack栈满了,或者出栈时栈为空会怎么样?

java中的队列实现

队列允许我们在尾部添加元素,并在头部删除元素,双端队列(Deque)允许我们在尾部和头部删除或者添加元素。

java.util.Queue<E>

LinkedList 实现了这个接口

  • boolean add(E element)
  • boolean offer(E element)
    如果队列没有满,则在尾部添加element并返回true,否则,add抛出IllegalStateException异常,offer返回false
  • E remove()
  • E poll()
    如果队列不为空,删除并返回队列头部元素,否则remove抛出NoSuchElementException,poll返回null
  • E element()
  • E peek()
    如果队列不为空,返回头部元素但不删除,否则element抛出NoSuchElementException,poll返回null

java.util.Deque<E> - 双端队列

  • boolean addFirst/addLast(E element)
  • boolean offerFirst/offerLast(E element)
    如果队列没有满,则在尾部添加element并返回true,否则,add抛出IllegalStateException异常,offer返回false
  • E removeFirst/removeLast()
  • E pollFirst/pollLast()
    如果队列不为空,删除并返回队列头部元素,否则remove抛出NoSuchElementException,poll返回null
  • E getFirst/getLast()
  • E peekFirst/peekLast()
    如果队列不为空,返回头部元素但不删除,否则element抛出NoSuchElementException,poll返回null

java.util.PriorityQueue - 优先级队列

无论何时调用remove方法,都能获得当前优先队列的最小元素,优先队列使用了一个高效的数据结构--heap堆,通过最小堆这种二叉树,可以将最小元素移动到根,不必花费时间对元素排序。优先队列的典型用法是任务调度,每个任务有一个优先级,任务随机添加到队列中。在每次启动时,将优先级最高的任务从队列中取出。

  • PriorityQueue(int initialCapacity,Comparator c)
    构建一个优先级队列,并使用指定的比较器对元素排序

题目一 用栈实现队列232. 用栈实现队列 - 力扣(LeetCode)

image.png

image.png

思路: 图片来源:代码随想录 (programmercarl.com)

image.png

  • 第一个栈模拟队列的添加尾部元素
  • 第二个栈模拟队列的删除头部元素

代码

注意:pop的复用要this.pop(),不能写成stackout.pop()

    public int peek() {
        // 先出栈
        int out = this.pop();
        // 再把元素放回stackout
        stackout.push(out);
        return out;
    }
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() {
        if(stackout.isEmpty()) {
            while(!stackin.isEmpty()) {
                stackout.push(stackin.pop());
            }
        }
        return stackout.pop();
    }
    
    public int peek() {
        int out = this.pop();
        stackout.push(out);
        return out;
    }
    
    public boolean empty() {
        return stackout.isEmpty() && stackin.isEmpty();
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

题目二 用队列实现栈225. 用队列实现栈 - 力扣(LeetCode)

image.png

image.png

image.png

思路:用一个队列模拟栈

  • 入栈,队列末尾添加元素
  • 出栈,除Last元素外,队列元素全部拿出来,依次添加到末尾;再删除头部元素就是了

代码

  • 怎么留下队列的最后一个元素? 答:利用size()方法得到队列长度
class MyStack {
    Queue<Integer> que;
    public MyStack() {
        que = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        que.offer(x);
    }
    
    public int pop() {
        int i = que.size();
        while(i-- > 1){
            int a = que.poll();
            que.offer(a);
        }
        return que.poll();
    }
    
    public int top() {
        int element = this.pop();
        this.push(element);
        return element;
    }
    
    public boolean empty() {
        return que.isEmpty();
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */

学习时长:2h