JAVA——链式队列、循环队列的基本用法


一、基本介绍

1.概念

队列:(先进先出)队尾入队头出

只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

入队列:

进行插入操作的一端称为队尾(Tail/Rear)

出队列:

进行删除操作的一端称为队头(Head/Front)

2.队列是用什么实现的?

以下写的一般队列的底层是由双向链表实现的,数组实现太麻烦。循环队列使用的是数组实现的。

二、JAVA集合类对应的队列(LinkedList)

入队列:
linkedList.add();容量受限时会抛出异常
linkedList.offer();容量受限时return true比add()更好。

出队列:linkedList.poll() ;

得到队头元素:linkedList.peek();

public static void main(String[] args){
            LinkedList<Integer> linkedList = new LinkedList<>();
            //只要把握住 先进先出就好了
            linkedList.add(1);
            linkedList.offer(2);
            linkedList.add(3);

            System.out.println(linkedList.peek());//1
            System.out.println(linkedList.poll());//1
            System.out.println(linkedList.isEmpty());//
        }

三、自己实现队列基本用法

1.初始化一个队列(链表)一定要定义头指针和尾指针
2.入队列,要考虑队列为空和只有一个链表的情况。
3.出队列,要考虑连表为空的情况
4.获得队列长度

class Node{
    public int data;//数据域
    public Node next;//指针

    public Node(int data) {
        this.data = data;
    }
}


public class MyQueueLinked {
    private  Node front;//头指针
    private  Node rear;//尾指针
    private  int usedSize;//队列长度


    /*
    * 入队列
    * @param val值
    * */
    public void offer(int val){
        Node node=new Node(val);
        if(this.front==null){
            this.front=node;
            this.rear=node;
        }else{
            this.rear.next=node;
            this.rear=node;
        }
        this.usedSize++;
    }


    /**
     * 出队头元素
     * @return
     */
    private boolean isEmpty() {
        return this.usedSize==0;
    }

    public int poll(){
        if(isEmpty()){
            throw new RuntimeException(("队列为空"));
        }
        int val=this.front.data;
        if(this.front.next==null){
            //只有一个结点
            this.front=null;
            this.rear=null;
        }else {
            this.front = this.front.next;
        }
        this.usedSize--;
        return val;
    }

    /**
     * 得到队头元素 但是不删除
     */

    public int peek(){
        if(isEmpty()){
            throw new RuntimeException(("队列为空"));
        }
        return this.front.data;

    }

    //获得队列长度
    public int size(){
        return this.usedSize;
    }


    public static void main1(String[] args) {
        MyQueueLinked myQueueLinked = new MyQueueLinked();
        myQueueLinked.offer(1);
        myQueueLinked.offer(2);
        myQueueLinked.offer(3);
        System.out.println(myQueueLinked.peek());//1
        System.out.println(myQueueLinked.poll());//1
        System.out.println(myQueueLinked.peek());//2
        System.out.println(myQueueLinked.poll());//2
        System.out.println(myQueueLinked.isEmpty());//false
        System.out.println(myQueueLinked.size());//
        System.out.println(myQueueLinked.poll());//3
        System.out.println(myQueueLinked.poll());//
    }
}

四、循环队列基本操作

1.为什么要引入循环队列

由于一般队列的每个链表只能进行一次性的使用,为了更加节省内存,引入了循环队列,这里写的是用数组实现的循环队列。

2.基本操作

1.开辟循环队列空间
2.入队:从队尾开始入,入完以后,rear要多走到下一格。要考虑队满的情况,若是rear下一个元素为front则队已满,由于rear要多走到下一格,front前一个格子永远是空的。
在这里插入图片描述
3.出队:要考虑为空的情况,当rear=front时队列为空。
在这里插入图片描述
4.得到队头元素:考虑队列是否为空,返回front所在位置元素即可
5.得到队尾元素:考虑队列是否为空,和队尾元素为0的情况(队满的时候rear在front前一格的时候),此时返回队列长度-1的值。若在其他位置,则返回rear-1位置的元素,因为他每次入完一个元素,都会走到下一格。

代码中的(this.rear+1)%this.elem.length可以代表rear.next,意思是指针向前走一步
public class MyCircularQueue {
    private  int[]elem;//开辟空间
    private  int useSize;//实际长度
    private  int front;//头指针
    private  int rear;//尾指针

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

/**
 * 入队
 * @param value
 * @return
 */

public boolean enQueue(int value) {
    if (isFull()) {
        return false;
    }
    this.elem[this.rear]=value;
    this.rear=(this.rear+1)%this.elem.length;//rear向前走一步
    return true;
}
    public boolean isFull() {
       if((this.rear+1)%this.elem.length==this.front){//rear.next的值等于front则满了
           return true;
       }
       return false;
   }

/**
 * 出队
 * @return
 */
public boolean deQueue(){
    if(isEmpty()){
        return false;
    }
    this.front=(this.front+1) % this.elem.length;//front向前走一步
    return true;

}
public boolean isEmpty(){
    if(this.rear==this.front){
        return true;
    }
    return false;
}

/**
 * 得到队头元素  相当于 peek()
 * @return
 */

public int Front(){
    if(isEmpty()){
        return -1;//循环队列不可以抛异常
    }
    int val=this.elem[this.front];
    return val;
}

/**
 * 得到队尾元素
 * @return
 */
public int rear(){
    if(isEmpty()){
        return -1;
    }
    if(this.rear==0){
        return this.elem[this.elem.length-1];
    }
    return  this.elem[this.rear-1];


}

}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值