第3讲 队列

84 阅读2分钟

队列

队列:是一个有序列表,可以用数组或是链表来实现。 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出。

模拟实现一个队列:

public class ArrayQueueDemo {
    public static void main(String[] args) throws Exception {
        ArrayQueue arrayQueue = new ArrayQueue(10);
        arrayQueue.add(5);
        arrayQueue.display();
        arrayQueue.add(10);
        arrayQueue.display();

        arrayQueue.get();
        arrayQueue.get();
        arrayQueue.get();
    }
}

//使用数组模拟队列-->编写一个ArrayQueue类
class ArrayQueue{
    private int maxSize;//队列最大长度
    private int front;//队列头
    private int rear;//队列尾
    private int[] arr;//存放数据

    public ArrayQueue(int size){
        maxSize=size;
        arr=new int[maxSize];
        //初始化时队列头尾都指向第一个元素下方位置
        front=-1;
        rear=-1;
    }

    //队列是否已经满了
    public boolean isFull(){
        return rear==maxSize-1;
    }

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

    //添加数据
    public void add(int e){
        if(isFull()){
            System.out.println("队列已经满了,不能添加~");
            return;
        }
        rear++;//后移一位
        arr[rear]=e;
    }

    //移除数据
    public int get() throws Exception {
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        front++;
        return arr[front];
    }

    //显示队列数据
    public void display(){
        if(isEmpty()){
            System.out.println("队列为空");
        }
        System.out.println("-------显示数据--------");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(i+"="+arr[i]);
        }
    }
     //显示头元素
     public int getHeader(){
       if(isEmpty()){
          throw new RuntimeException("队列为空");
       }
      return arr[front+1];
    }
}

示意图: image.png

存在问题:当元素移除后,下标上移,之前元素依然存在,无法继续添加数据。

环形队列

环形队列在逻辑上是环形的, 但在物理上是一个定长的数组。

image.png

针对上例存在问题,我们做如下调整:

1.front指向第一个元素索引,即arr[front] 就是数组第一个元素

2.rear指向最后一个元素的后一个位置

3.当队列满的条件是:(rear+1)%maxSize=front

4.队列为空条件是:rear==front

代码:

public class CirceArrayQueueDemo {
    public static void main(String[] args) throws Exception {
        CirceArrayQueue arrayQueue = new CirceArrayQueue(3);//设置为3 实际有效长度为2
        arrayQueue.add(5);
        arrayQueue.add(10);
        arrayQueue.display();
        arrayQueue.get();
        System.out.println("取出一个元素后,对头元素:"+arrayQueue.getHeader());
        arrayQueue.add(7);
        arrayQueue.add(4);
        arrayQueue.display();
    }
}

class CirceArrayQueue{
    private int maxSize;//队列最大长度
    private int front;//队列头 指向第一个位置
    private int rear;//队列尾  指向最后元素位置后一位
    private int[] arr;//存放数据

    public CirceArrayQueue(int size){
        maxSize=size;
        arr=new int[maxSize];
        //初始化时队列头尾都指向第一个元素
        front=0;
        rear=0;
    }

    //队列是否已经满了
    public boolean isFull(){
        return (rear+1)%maxSize==front;
    }

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

    //添加数据
    public void add(int e){
        if(isFull()){
            System.out.println("队列已经满了,不能添加~");
            return;
        }
        arr[rear]=e;
        rear=(rear+1)%maxSize;
    }

    //取出数据
    public int get() throws Exception {
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
       int value=arr[front];
        //front后移考虑取模
        front=(front+1)%maxSize;
        return value;
    }

    //显示队列数据
    public void display(){
        if(isEmpty()){
            System.out.println("队列为空");
            return;
        }
        System.out.println("-------显示数据--------");
        //从front开始遍历,遍历多少个元素
        for (int i = front; i < front+size(); i++) {
            System.out.println(i%maxSize+"="+arr[i%maxSize]);
        }
    }

    //求出当前队列有效数据
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }

    //显示头元素
    public int getHeader(){
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        return arr[front];
    }
}