Bootstrap

队列——使用数组实现环形队列(2)

2.2.4 数组模拟环形队列


对前面的数组模拟队列的优化,充分利用数组,因此将数组看作为一个环形的。(通过取模的方式实现即可)

分析说明

  1. 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,判断队列满的条件为:(rear+1)%maxSize ==front 表示队列已满

  2. rear == front 表示队列为空

  3. 分析示意图:

在这里插入图片描述

思路如下:

  1. front 变量的含义做一个调整:front 指向队列的第一个元素,也就是说arr[front] 就是队列的第一个元素,front 的初始值等于0
  2. rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置,因为想空出一个空间作为约定,rear 的初始值等于0
  3. 当队列满时,条件是 (rear+1) % maxSize = front
  4. 当队列为空时,条件是 rear=front
  5. 队列中有效元素的个数为:(rear + maxSize - front) % maxSize
  6. 在此基础上,修改得到一个环形队列

代码实现:

public class CircleArrayQueueDemo {

    public static void main(String[] args) {

        //小测一把
        System.out.println("测试数组模拟环形队列");
        CircleArray arrayQueue = new CircleArray(4);
        //接收用户输入
        char key =' ';
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        //输出一个菜单
        while (loop){
            System.out.println("s(show): 显示队列");
            System.out.println("e(exit): 退出程序");
            System.out.println("a(add): 添加数据到队列");
            System.out.println("g(get): 从队列取出数列");
            System.out.println("h(head): 查看队列头的数据");
            //接受字符
            key = scanner.next().charAt(0);
            switch (key){
                case 's':
                    arrayQueue.showQueue();
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                case 'a':
                    System.out.println("请输入一个数:");
                    int i = scanner.nextInt();
                    arrayQueue.addQueue(i);
                    break;
                case 'g':
                    arrayQueue.getQueue();
                    break;
                case 'h':
                    System.out.println("队列头的数据为:");
                    arrayQueue.getFront();
                    break;
                default: break;
            }
        }
        System.out.println("程序退出");
    }

}

    /**
     * 使用数组模拟环形队列
     */
    class CircleArray {

        /**
         * 表示数组的最大容量
         */
        private int maxSize;
        /**
         * 队列头,指向队列头的第一个数据
         */
        private int front;
        /**
         * 队列尾,指向队列尾部的后一个位置
         */
        private int rear;
        /**
         * 用于存放队列中的数据,模拟队列
         */
        private int[] arr;

        /**
         * 创建队列的构造器
         */
        public CircleArray(int maxSize) {
            this.maxSize = maxSize;
            arr = new int[maxSize];
            //指向队列头部,指向队列头的第一个数据
            front = 0;
            //指向队列尾部的后一个位置
            rear = 0;
        }

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

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

        /**
         * 添加数据到队列
         */
        public void addQueue(int m) {
            //判断队列是否满
            if (isFull()) {
                System.out.println("队列已满,不能再添加数据");
                return;
            }
            //rear后移,并将数据存入其中
            arr[rear] = m;
            rear = (rear+1)%maxSize;
        }

        /**
         * 出队列,获取队列的数据
         */
        public void getQueue() {
            //判断队列是否为空
            if (isEmpty()) {
                System.out.println("队列为空,没有数据可以获取了");
                return;
            }
            System.out.println("获取到的数据为:" + arr[front]);
            //front后移
            front = (front+1)%maxSize;
        }

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

        /**
         * 显示队列的所有数据
         */
        public void showQueue() {
            //判断队列是否为空
            if (isEmpty()) {
                System.out.println("队列为空,没有数据可以获取了");
                return;
            }
            for (int i = front; i < front+count(); i++) {
                System.out.printf("arr[%d]=%d\n", i%maxSize, arr[i%maxSize]);
            }
        }

        /**
         * 显示队列的头数据,注意:不是取数据
         */
        public void getFront() {
            if (isEmpty()) {
                System.out.println("队列为空,没有数据可以获取了");
                return;
            }
            System.out.println("队列的头数据为:" + arr[front]);
        }
    }

;