队列(Queue)

1 .概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front)

2 .队列的方法

3.队列的实现(这里我们使用单链表来实现队列)

package Queue;
//用单链表实现队列
public class MyQueue {
    //队列是:先进先出(头删尾插)
    static class Node{
        public int val;
        public Node next;
        public Node(int val){
            this.val=val;
        }

    }
    public Node head;
    public Node last;
    public int usedSize;
    //入队
    public void offer(int val){
        Node node=new Node(val);
        if(head==null){
            head=node;
        }else{
            last.next=node;
        }
        last=node;
        usedSize++;
    }
    //出队
    public int poll(){
        //此处得判断此时队列是否为空
        if(isEmpty()){
            return -1;// 一般这里得抛异常,但是在牛客或力扣上等写返回值-1
        }
        int ret=head.val;
        head=head.next;
        usedSize--;
        return ret;

    }
    private boolean isEmpty(){
        return usedSize==0;
    }
    //获取队首元素
    public int peek(){
        //此处得判断此时队列是否为空
        if(isEmpty()){
            return -1;// 一般这里得抛异常,但是在牛客或力扣上等写返回值-1
        }
        return  head.val;

    }
    //获取队列长度
    public int getUsedSize(){
        return usedSize;
    }

}

4 循环队列

实际中我们有时还会使用一种队列叫循环队列,环形队列通常使用数组实现。

  • 数组下标循环:rear=(rear+1)%数组.length

此处目的是让下标可以从7到0下标出,以此来达到循环效果

  • 如何判断队列是否为满

1:使用usedSize来记录队列长度,以此来判断是否为满

2:牺牲一个空间,通过rear+1(此处表示牺牲的数组空间下标)与数组长度求模来判断是否与front相等,相等则为 满,反之不满。

package Queue;

public class MyCircularQueue {
    //设计循环队列[先进先出]
    //这里用数组来实现
    private int[] elem;//定义一个数组
    private int front;//用来表示队列的头
    private int rear;//用来表示队列的尾

    public MyCircularQueue(int k) {
        this.elem = new int[k + 1];//这里我们是牺牲一个空间来做的,因此K+1来多给一个空间

    }

    //入队列
    public boolean enQueue(int value) {
        //1.检查队列是否为满
        if (isFull()) {
            return false;
        }
        elem[rear] = value;
        //rear++;
        // [此处不能是rear++,因为该数组为循环数组,如果使用rear++时,当rear走到elem.length-1时,就不能走到0下标位置]
        rear = (rear + 1) % elem.length;
        return true;
    }

    //出队列
    public boolean deQueue() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % elem.length;
        return true;

    }

    //头元素
    public int Front() {
        if (isEmpty()) {
            return -1;
        }
        return elem[front];

    }

    //尾元素
    public int Rear() {
        if (isEmpty()) {
            return -1;
        }
        int index = (rear == 0) ? (elem.length - 1) : (rear - 1);
        //此处为rear-1时因为我们牺牲一个空间来表示在是否为满,
        // 而rear时那个数组空间的下标因此求尾元素等让rear-1
        return elem[index];


    }

    //判断队列是否为空
    public boolean isEmpty() {
        return rear == front;

    }

    //判断队列是否为满
    public boolean isFull() {
        //【这里有两种方法 1:加一个usedSize来表示数组长度,当长度等于k即表示满了
        // 2:牺牲一个数组空间,通过rear+1(此处表示牺牲的数组空间下标)与数组长度求模来判断是否与front相等,
        // 若相等即表示满了,反之没有满[这里我们使用第二种方法]】
        /*if((rear+1)%elem.length==front){
            return true;
        }
        return false;*/
        return (rear + 1) % elem.length == front;

    }
}

5. 双端队列 (Deque)

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

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

使用Deque接口是比较多的,栈和队列均可以使用该接口

  • Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现 (数组实现的双端列)

  • Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现 (链表实现的双端队列)

  • Queue<Integer> queue =new LinkedList<>();//队列

  • LinkedList<Integer> stack =new LinkedList<>();//队列栈 (双向链表实现的栈)

  • List<Integer> list =new LinkedList<>();//双向队列

注意:在队列中,offerFirst()方法优于addFirst()方法,因为add方法无法插入元素时,会抛异常【一般情况下我们使用offerFirst()方法会比较多】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值