03-队列

1. 简单介绍

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

2. 数组模拟队列

  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear 则是随着数据输入而改变。
  • 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。
  • 当我们将数据存入队列时称为"addQueue",addQueue 的处理需要有 2 个步骤
    • 将尾指针往后移:rear+1,当 front == rear [队列空]
    • 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。 rear == maxSize - 1 [队列满]

3. 代码实现

public class ArrayQueue {
    // 表示数组最大容量
    private int maxSize;
    // 队列首元素之前的元素的下标
    private int front;
    // 队列尾元素下标
    private int rear;
    // 用来存放数据(模拟队列)
    private int[] arr;

    // 队列构造器
    public ArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
        // 队列首有效元素的前一个位置的索引
        front = -1;
        // 队列尾最后一个有效元素的索引
        rear = -1;
    }

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

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

    // 入列
    public void addQueue(int val) {
        // 判断是否满
        if (isFull()) {
            System.out.println("队列满");
            return;
        }
        arr[++rear] = val;
    }

    // 出列
    public int getQueue() {
        // 判断是否空
        if (isEmpty()) throw new RuntimeException("队列空");
        return arr[++front];
    }

    // 打印队列数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列空");
            return;
        }
        for (int i = 0; i < maxSize; i++)
            System.out.printf("arr[%d] = %d
", i, arr[i]);
    }

    // 显示首有效元素(不是取)
    public int headQueue() {
        if (isEmpty()) throw new RuntimeException("队列空");
        return arr[front + 1];
    }
}

4. 进阶:循环队列

上面的代码还有些问题,数组不能复用,造成内存浪费。使用传统数组来构造队列,无论是出队还是入队都是指针在往后移;那么,之前的出队元素所在的数组元素空间就全被浪费了,所以必须让它成个"⚪"。即 当指针指向「end 元素」,再往后移,就会又循环回来,指向了 「first 元素」。

  • 队列初始化:front 和 rear 的值都是 0
  • 队列非空
    • front 指向队列的第一个有效元素
    • rear 指向队列最后一个有效元素的下一个元素
  • 队列空:front == rear(不一定非得都等于 0)
  • 队列满:队列最多存放的有效数据个数:array.length - 1。即:当 (rear+1) % length == front,表示队列已满
  • 队列有效元素个数:count = (rear - front + maxSize) % maxSize
    • 当 rear > front,相减得到的就是 {有效元素个数},加 maxSize 再取余还是它本身
    • 当 rear < front,相减得到的是 [ - {空闲位置数} ],加上 maxSize ,就正好是 {有效元素个数} ,再取余,还是 {有效元素个数}

5. 代码优化

public class CircleArrayQueue {
    // 表示数组最大容量
    private int maxSize;
    // 队列首元素下标
    private int front;
    // 队列尾元素的后一个位置的下标
    private int rear;
    // 用来存放数据(模拟队列)
    private int[] arr;

    // 队列构造器
    public CircleArrayQueue(int maxSize) {
        this.maxSize = maxSize + 1;
        // 因为需要保留其中一个位置作为 [标识位], 故创建的数组大小要大一个元素空间
        arr = new int[maxSize + 1];
        // 初始化
        front = 0;
        rear = 0;
    }

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

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

    // 入列
    public void addQueue(int val) {
        // 判断是否满
        if (isFull()) {
            System.out.println("队列满");
            return;
        }
        arr[rear] = val;
        // rear 后移时要考虑到:rear 指向的是数组末尾位置
        rear = (rear + 1) % maxSize;
    }

    // 出列
    public int getQueue() {
        // 判断是否空
        if (isEmpty()) throw new RuntimeException("队列空");
        int val = arr[front];
        // front 后移时要考虑到:front 指向的是数组末尾位置
        front = (front + 1) % maxSize;
        return val;
    }

    // 当前队列有效元素个数
    public int getCount() {
        return (rear - front + maxSize) % maxSize;
    }

    // 打印队列数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列空");
            return;
        }
        // 思路:从front开始遍历,遍历count个元素
        int count = getCount();
        for (int i = front; i < front + count; i++)
            System.out.printf("arr[%d] = %d
", i%maxSize, arr[i%maxSize]);
    }

    // 显示首有效元素(不是取)
    public int headQueue() {
        if(isEmpty()) throw new RuntimeException("队列空");
        return arr[front];
    }
}
原文地址:https://www.cnblogs.com/liujiaqi1101/p/12214382.html