三分钟“手撕”队列与习题

代码放开头,方便大家查阅

目录

一、实现代码

二、什么是队列

三、队列常见方法

入队push()  

出队 

四、Queue使用

Java自带的Queue 

双端队列 

五、习题

循环队列

用队列实现栈

用栈实现队列


一、实现代码

package demo2;

public class MyQueue {

    class ListNode{
        ListNode prev;
        ListNode next;
        int var;

        public ListNode(int var) {
            this.var = var;
        }
    }
    ListNode first;
    ListNode last;
    int size=0;


    public void offer(int val) {
        ListNode node=new ListNode(val);
        if(isEmpty()){
            first=last=node;
        }else {
            last.next = node;
            node.prev = last;
            last = last.next;
        }size++;
    }

    public int poll() {
        int var=0;
        if(first==null){
            return -1;
        }else if(first==last){
            first=last=null;
        }else {
            var=first.var;
            first.next.prev=null;
            first=first.next;
        }--size;
        return var;
    }

    public int peek(){
        if(isEmpty()){
            return -1;
        }
        return first.var;
    }


    public boolean isEmpty() {
        return 0==size;
    }
}

二、什么是队列

简单来讲:先进先出的队伍!  

假设第一个入队(push)的是1,第二个2 第三个3,那么先进先出的队伍,出来(pop)的是1,然后pop是2,pop是3。

三、队列常见方法

 队列中有两种实现方式:一种是数组,一种是链表,

(Java中的队列也是采用链表实现的)这里我采用链表讲解。 

入队push()  

简单讲:多一个人排队!

入队都是往最后一个节点那里再加一个元素!

出队 

简单来说:排队排到了,买完东西就走了(谁先排到,谁先走) 

把第一次进入的元素蹦出来(删掉) 就行了

四、Queue使用

Java自带的Queue 

 在Java中,Queue是个接口,底层是通过链表实现的。

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检测队列是否为空

 注意:

Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

public static void main(String[] args) {
        Queue<Integer> q = new LinkedList<>();
        q.offer(1);
        q.offer(2);
        q.offer(3);
        q.offer(4);
        q.offer(5); // 从队尾入队列
        System.out.println(q.size());
        System.out.println(q.peek()); // 获取队头元素
        q.poll();
        System.out.println(q.poll()); // 从队头出队列,并将删除的元素返回
    if(q.isEmpty()){
        System.out.println("队列空");
    }else{
        System.out.println(q.size());
    }
}

双端队列 

 双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。

那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

 Deque是一个接口,使用时必须创建LinkedList的对象。 (如下图左下角LinkedList和右边Deque)

所以,我们如果要使用双端队列,应该写出如下代码:

Deque<Integer> queue1 = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue2 = new LinkedList<>();//双端队列的链式实现

五、习题

循环队列

思路如下:

如何循环?当下标为7时,如果再让last往下走last+1就是8就越界了,所以你需要有个方法,就是last=(last+1)%array.length,比如(7+1)%8=0,所以又是来一轮。

注意上图,比如这个last不是指6下标而是指7下标。

class MyCircularQueue {
    int[] elem;
    int first;
    int last;

    public MyCircularQueue(int k) {
        elem = new int[k];
    }

    public boolean enQueue(int value) {
        if (isFull()) {
            return false;
        }
        elem[last] = value;
        last = (last + 1) % elem.length;
        return true;
    }

    public boolean deQueue() {
        if (isEmpty()) {
            return false;
        }
        first = (first+1)%elem.length;
        return true;
    }

    public int Front() {
        if (isEmpty()) {
            return -1;
        }
        return elem[first];
    }

    public int Rear() {
        if (isEmpty()) {
            return -1;
        }
        int index=(last==0)?elem.length-1:last-1;
        return elem[index];
    }

    public boolean isEmpty() {
        return first == last;
    }

    public boolean isFull() {
        return first == (last + 1) % elem.length;
    }
}

注意的是,即使一模一样是上面的代码,也需要在构造函数的时候k+1,才不会报错。

用队列实现栈

 思路如下:

一个队列肯定是实现不了栈的!为什么?

答:因为一个先进先出,一个先进后出,机制都不一样。所以需要两个队列。

怎么实现呢?

出栈:把一个队列的N-1个元素pop到空一个队列当中!当前队列剩下的一个元素就是我们需要“出栈”的元素!

入栈:把数据放到部位空的队列当中。

注意:第一次入栈时,两个队列都为空,那就放第一个。

import java.util.ArrayDeque;

class MyQueue {

    public ArrayDeque<Integer> s1;
    public ArrayDeque<Integer> s2;
    public MyQueue() {
        s1 = new ArrayDeque<>();
        s2 = new ArrayDeque<>();
    }

    public void push(int x) {
        s1.push(x);
    }

    public int pop() {
        //2个栈都是空 意味着 队列为空
        if(empty()) {
            return -1;
        }
        if(s2.isEmpty()) {
            while (!s1.isEmpty()) {
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }

    public int peek() {
        if(empty()) {
            return -1;
        }
        if(s2.isEmpty()) {
            while (!s1.isEmpty()) {
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }

    public boolean empty() {
        return s1.isEmpty() && s2.isEmpty();
    }
}

用栈实现队列

 思路如下:

入栈:放到第一个栈中

出栈:把第一个栈所有的元素全部放入第二个栈中,第二个栈里面的元素出栈入栈就已经是队列的排法了,如果第二个栈是空的,那么把第一个栈的都拿过来。

import java.util.ArrayDeque;

class MyQueue {

    public ArrayDeque<Integer> s1;
    public ArrayDeque<Integer> s2;
    public MyQueue() {
        s1 = new ArrayDeque<>();
        s2 = new ArrayDeque<>();
    }

    public void push(int x) {
        s1.push(x);
    }

    public int pop() {
        //2个栈都是空 意味着 队列为空
        if(empty()) {
            return -1;
        }
        if(s2.isEmpty()) {
            while (!s1.isEmpty()) {
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }

    public int peek() {
        if(empty()) {
            return -1;
        }
        if(s2.isEmpty()) {
            while (!s1.isEmpty()) {
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }

    public boolean empty() {
        return s1.isEmpty() && s2.isEmpty();
    }

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值