代码随想录算法训练营day09||栈与队列理论基础||232.用栈实现队列||225. 用队列实现栈

Day09

栈与队列理论基础


Java中的Stack类

  • Stack是Vector的一个子类,它实现标准的后进先出堆栈。Stack只定义了创建空堆栈的默认构造方法。

public class Stack<E> extends Vector<E> public Stack() {}

  • Stack类里面主要实现的有以下的几个方法:

  • boolean empty( )方法是判断堆栈是否为空。

  • 需要有一个变量来计算当前栈的长度,若变量的值为0,说明这个栈是空的

  • Object peek( )方法是返回栈顶端的元素,但不从堆栈中移除它。

  • Object pop( )方法是移除堆栈顶部的对象,并作为此函数的值返回该对象。

  • Object push (Object element)方法是把元素压入栈。

  • int search(Object element)方法是返回对象在堆栈中的位置,它是以1为基数。

  • 其实就是距离栈顶元素的距离,如果是栈顶元素返回1,如果没找到返回-1

Java中的队列

  • 基本概念

  • 阻塞和非阻塞

  • 阻塞队列

  • 入列(添加元素)时,如果元素数量超过队列总数,会进行等待(阻塞),待队列的中的元素出列后,元素数量未超过队列总数时,就会解除阻塞状态,进而可以继续入列;

  • 出列(删除元素)时,如果队列为空的情况下,也会进行等待(阻塞),待队列有值的时候即会解除阻塞状态,进而继续出列;

  • 阻塞队列的好处是可以防止队列容器溢出;只要满了就会进行阻塞等待;也就不存在溢出的情况;

  • 只要是阻塞队列,都是线程安全的;

  • 特有的方法

  • put 添加一个元素 如果队列满,则阻塞take 移除并返回队列头部的元素 如果队列为空,则阻塞

  • 非阻塞队列

  • 不管出列还是入列,都不会进行阻塞,

  • 入列时,如果元素数量超过队列总数,则会抛出异常,

  • 出列时,如果队列为空,则取出空值;

  • 一般情况下,非阻塞式队列使用的比较少,一般都用阻塞式的对象比较多;

  • 有界和无界

  • 有界:有界限,大小长度受限制

  • 无界:无限大小,其实说是无限大小,其实是有界限的,只不过超过界限时就会进行扩容,就和ArrayList 一样,在内部动态扩容

  • Quene和Deque

  • Quene以及Deque都是继承于Collection,Deque是Quene的子接口。

  • Quene是先进先出的单向队列,Deque是双向队列。

  • 也就是说Deque是Queue的子类,可以把它当作队列来使用。

  • Deque支持两端元素插入和移除的线性集合。也就是Deque可以在两边都操作元素:新增、删除、访问元素等。而Quene 只能在队首对元素进行操作。

  • Quene

  • Quene是集合框架Collection的子接口,是一种常见的数据结构,Quene有一个子类PriorityQuene,队列Quene是一种常用的数据结构,可以将队列看作是一种特殊的线性表,该结构遵循的先进先出原则。

  • Java中,LinkedList实现了Quene接口,因为LinkedList进行插入、删除操作效率较高。

  • add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常offer 添加一个元素并返回true 如果队列已满,则返回falsepoll 移除并返问队列头部的元素 如果队列为空,则返回nullpeek 返回队列头部的元素 如果队列为空,则返回null

实现方法

栈的实现:

Deque stack=new ArrayDeque();

Deque stack = new LinkedList();

双端队列 Deque 可用作 LIFO(后进先出)堆栈。应优先使用此接口而非遗留 Stack 类。在将Deque 用作 Stack 时,元素被推入 Deque 的开头并从 Deque 开头弹出。Stack 方法完全等效于 Deque 方法,如下表所示:

堆栈方法

等效 Deque方法

push(e)

addFirst(e)

pop()

removeFirst()

peek()

peekFirst()

Stack类继承了Vector,需要保证线程安全,效率就很低

4、队列的实现:Queue queue = new LinkedList();

Queue 除了基本的 Collection 操作外,还提供其他的插入、提取和检查操作。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null / false)。

抛出异常

返回特殊值

插入

add(e)

offer(e)

移除

remove()

poll()

检查

element()

peek()

Deque 接口扩展了 Queue 接口。在将 Deque 用作队列时,将得到 FIFO(先进先出)行为。Deque 接口提供插入、移除和检查元素的方法。

第一个元素(头部) 最后一个元素(尾部) 抛出异常 特殊值 抛出异常 特殊值插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e)移除 removeFirst() pollFirst() removeLast() pollLast()检查 getFirst() peekFirst() getLast() peekLast()此外,从 Queue 接口继承的方法完全等效于 Deque 方法。

Queue 方法

等效 Deque 方法

add(e)

addLast(e)

offer(e)

offerLast(e)

remove()

removeFirst()

poll()

pollFirst()

element()

getFirst()

peek()

peekFirst()

232.用栈实现队列


力扣题目链接

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。pop() -- 从队列首部移除元素。peek() -- 返回队列首部的元素。empty() -- 返回队列是否为空。

思路

  • 队列是先入先出,栈是先入后出,更重要的是栈只有一个口,所以必须要用两个栈才能模拟队列

  • 一个stackIn一个stackOut

  • 关键是定义一个内置函数,把stackIn里面的元素倒入stackOut中

  • 加入元素就在stackIn里面加

  • pop元素的时候,要看看stackOut有没有元素,有就pop,没有就调用内置函数,再pop即可

  • peek元素很多代码和pop重复,可以先pop,再放到stackOut里面

  • 当stackIn和stackOut均空,队列为空

代码

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() {
        if (!stackOut.isEmpty()){
            return stackOut.pop();
        }
        dumpStackIn();
        return stackOut.pop();
    }

    public int peek() {
        int ans = pop();
        stackOut.push(ans);
        return ans;
    }

    public boolean empty() {
        return stackOut.isEmpty() && stackIn.isEmpty();
    }

    private void dumpStackIn(){
        int temp;
        while (!stackIn.isEmpty()){
            temp = stackIn.pop();
            stackOut.push(temp);
        }
    }
}

225. 用队列实现栈


力扣题目链接

使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈

  • pop() -- 移除栈顶元素

  • top() -- 获取栈顶元素

  • empty() -- 返回栈是否为空

思路

  • 使用一个队列即可

  • 如果使用双端队列,这个题就没意思了,直接调用对应的API即可

  • 我们考虑使用单端队列,由于队列有两个口,一个入一个出,我们的思路是:

  • 加入元素直接加,区别是移除元素

  • 因为栈要移除的是栈顶的元素,这时这个元素因为是最后加入的,应该在队列尾

  • 所以我们可以使用循环,把除了栈顶元素的其他元素pop或poll出队列,然后再加入即可

代码

class MyStack {

    Deque<Integer> quene;

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

    public void push(int x) {
        quene.add(x);
    }

    public int pop() {
        return quene.removeLast();
    }

    public int top() {
        int ans = pop();
        push(ans);
        return ans;
    }

    public boolean empty() {
        return quene.isEmpty();
    }
}
class MyStack1 {

    Deque<Integer> quene;

    public MyStack1() {
        quene = new LinkedList<>();
    }

    public void push(int x) {
        quene.add(x);
    }

    public int pop() {
        for (int i = 0; i < quene.size() - 1; i++) {
            int temp = quene.poll();
            quene.add(temp);
        }
        return quene.poll();
    }

    public int top() {
        int ans = pop();
        push(ans);
        return ans;
    }

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

注意:

pop() 方法等价于removeFirst(), 底层调用的是removeFirst()方法。poll()方法等价于pollFirst() 方法,底层调用的是pollFirst()。两个方法的区别在于如果deque是空的(Empty) poll方法会返回null, pop方法会抛出异常NoSuchElementException()。这也是removeFirst(), pollFirst()方法的区别。实际上,removeFirst底层调用的也是pollFirst方法,只是增加了一个null的判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值