zoukankan      html  css  js  c++  java
  • 队列篇之使用环型数组模拟一个队列

    在上一篇随笔中使用数据模拟了一个队列,但是有缺陷, 数组只能使用一次,原因是index指针一直往上++, 不能回到数组之前的位置. 

    ArrayBlockingQueue源码给出了一种实现方案, 它是在判断队列(数组)满了之后,直接将putIndex重置为0, 这样offer元素到队列时,又可以利用数组之前的空间了.

    下面使用环型数组的方式来实现数组的重复利用.

    代码如下

    public class CircleArrayQueueDemo {
        public static void main(String[] args) {
            // 入参为4,但是队列最多只能存放3个元素,因为在判断队列是否满的时 (rear+1) 了
            CircleArrayQueue circleArrayQueue = new CircleArrayQueue(4);  
            circleArrayQueue.add(1);
            circleArrayQueue.show();
            System.out.println("-----------------------------");
            circleArrayQueue.add(2);
            circleArrayQueue.show();
            System.out.println("-----------------------------");
            circleArrayQueue.add(3);
            circleArrayQueue.show();
            System.out.println("-----------------------------");
            circleArrayQueue.pop(); // 将队列首位的元素取走
            circleArrayQueue.add(4);
            circleArrayQueue.show();
            System.out.println("-----------------------------");
            circleArrayQueue.pop();
            circleArrayQueue.add(5);
            circleArrayQueue.show();
    
        }
    }
    
    class CircleArrayQueue {
        /**
         * 队列最大容量
         */
        private int maxSize;
    
        /**
         * 队列头指针,指向队列的第一个元素, 初始值0
         */
        private int front;
    
        /**
         * 队列尾指针, 初始始0
         */
        private int rear;
    
    
        /**
         * 存放数据的数组
         */
        private int[] arr;
    
    
        // 创建队列的构造器
        public CircleArrayQueue(int maxSize) {
            this.maxSize = maxSize;
            arr = new int[maxSize];
        }
    
        /**
         * 判断队列是否已满
         *
         * @return
         */
        public boolean isFull() {
            return (rear + 1) % maxSize == front;  // 因为这儿加了1,所以队列中能存放元素的个数应该等于 (maxSize -1)
        }
    
        public boolean isEmpty() {
            return rear == front;
        }
    
    
        public void add(int data) {
            if (isFull()) {
                System.out.println("队列已满");
                return;
            }
    
            // 因为rear直接指向的是队列最后一个元素的后一个位置,所以添加元素时,直接放到rear指针处即可
            arr[rear] = data;
            // 添加元素之后,重新计算rear的位置
            rear = (rear + 1) % maxSize;
        }
    
        /**
         * @return 队列头部的数据
         */
        public int pop() {
            if (isEmpty()) {
                throw new RuntimeException("队列为空, 不能取数据");
            }
            // 因为front指向了队列的第一个元素,
    
            int value = arr[front];
            front = (front + 1) % maxSize;  // 将front 后移一位, 取模是为了重回首位
            return value;
    
        }
    
        /**
         * 显示队列的头元素
         *
         * @return 队列头部的数据
         */
        public int peek() {
            if (isEmpty()) {
                throw new RuntimeException("队列为空, 不能peek数据");
            }
            return arr[front];
        }
    
    
        public void show() {
            if (isEmpty()) {
                System.out.println("队列空,无数据");
                return;
            }
            // 从front开始遍历
    
            for (int i = front; i < front + count(); i++) {
                System.out.printf("arr[%d] = %s
    ", i % maxSize, arr[i % maxSize]);
            }
        }
    
        /**
         * 当前队列元素的个数
         *
         * @return
         */
        public int count() {
            return (rear + maxSize - front) % maxSize;  // 当前队列的有效个数
        }
    }

    总的来说,该方案使用取模的方式来实现数组index的移动,这很容易理解. 

    但是isFull方法却有点意思 .

    假设队列maxSize = 3

    添加第1个元素1:

    add(1)  之后  rear = 1, front = 0

    添加第2个元素2:

    add(2)  之后 rear = 2, front = 0 

    此时,再添加第3个元素3:

    add(3) 时,先执行isFull方法,  (2+1)%3=0 , 等于front, 所以满了.

    如果pop首个元素:

    pop() , front = (0+1)%3 =1

    再add(3): 先调用isFull方法, (2+1)%3=0 , 不等于front, 所以没满, 可以添加  arr[2] = 3

  • 相关阅读:
    论财务的意义
    项目忙乱的原因
    回家的路
    但问耕耘
    做自己的主角
    坚持的意义
    觉醒的意义
    梦想的力量
    把自己当作一件艺术品
    九宫格年度计划
  • 原文地址:https://www.cnblogs.com/z-qinfeng/p/12131039.html
Copyright © 2011-2022 走看看