动态循环数组实现队列 (Java)

不想讲解,直接上代码.需要学习的直接看注释.

/**
 * @author Relic
 * @desc 动态循环数组实现队列
 * @date 2019-12-10 16:53
 */
public class DynamicArrayQueue<E> {

    private static final int DEFAULT_SIZE = 16;
    /**
     * 队首索引
     */
    private int front;
    /**
     * 队尾索引
     */
    private int rear;
    /**
     * 实现当前队列数组的实际容量
     */
    private int capacity;
    /**
     * 实际数据
     */
    private Object[] data;

    public DynamicArrayQueue() {
        this(DEFAULT_SIZE);
    }

    /**
     * 将队首队尾都标识为 -1 表示队列的初始化
     *
     * @param capacity 给定初始容量,将实际存储数据的数组初始化
     */
    public DynamicArrayQueue(int capacity) {
        front = -1;
        rear = -1;
        this.capacity = capacity;
        data = new Object[capacity];
    }

    /**
     * 判断队列是否已经满了
     *
     * @return 队列是否已满
     */
    public boolean isFull() {
        //这里先队尾 +1 再对容量取余可以取到当 rear 已经达到最大容量时的实际位置
        return (rear + 1) % capacity == front;
    }

    /**
     * 判断队列是否已经空了
     *
     * @return 队列是否已空
     */
    public boolean isEmpty() {
        return front == -1;
    }

    /**
     * 获取当前队列的长度
     *
     * @return 当前队列中元素的个数
     */
    public int size() {
        if (front == -1) {
            return 0;
        }
        //如果刚好满了,取余之后会得到 0,所以要判断下 size (这里加上一个容量是因为 rear - front 可能是 负的)
        int size = (rear - front + 1 + capacity) % capacity;
        return size == 0 ? capacity : size;
    }

    /**
     * 数组扩容
     */
    private void resize() {
        //扩容到两倍
        capacity = capacity * 2;
        Object[] oldData = data;
        data = new Object[capacity];
        // 将源数据复制到新的数组中
        System.arraycopy(oldData, 0, data, 0, oldData.length);
        /*
         当队尾小于队首时,说明队尾的索引已经到了队首的前面
         所以要将从 0 到队尾的元素移动到原数组最大容量位置之后
         将新数组原位置置为 null 垃圾回收
         */
        if (rear < front) {
            int initCapacity = capacity / 2;
            for (int i = 0; i < rear; i++) {
                data[initCapacity + i] = oldData[i];
                data[i] = null;
            }
            rear = rear + initCapacity;
        }
    }

    /**
     * 入队操作
     */
    public void enQueue(E element) {
        //判断队列是否已满,如果已经满了则需要进行扩容
        if (isFull()) {
            resize();
        }
        //确定当前队尾的索引值,因为是循环数组,环可能已经超出 capacity 的大小
        rear = (rear + 1) % capacity;
        data[rear] = element;
        //当队首还处于初始化状态时,将队首置为 0 (进这个逻辑时 rear 只能是 0)
        if (front == -1) {
            front = rear;
        }
    }

    /**
     * 出队一个元素
     *
     * @return 队首的元素
     */
    @SuppressWarnings("unchecked")
    public E deQueue() {
        //如果栈空了,抛出异常
        if (isEmpty()) {
            throw new RuntimeException("队列已空");
        }
        E current = (E) data[front];
        //当队首已经到了队尾的时候, 说明队列已空, 将队列返回初始化状态
        if (front == rear) {
            front = rear = -1;
        } else {
            front = (front + 1) % capacity;
        }
        return current;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size(); i++) {
            if (i != 0) {
                sb.append(",");
            }
            sb.append(data[(front + i) % capacity].toString());
        }
        sb.append("]");
        return sb.toString();
    }

}

测试类

import org.junit.Test;

public class DynamicArrayQueueTest {

    @Test
    public void queue() {
        DynamicArrayQueue<Integer> queue = new DynamicArrayQueue<>();
        queue.enQueue(2);
        queue.enQueue(5);
        queue.enQueue(4);
        queue.enQueue(3);
        queue.enQueue(1);
        queue.deQueue();
        queue.deQueue();
        System.out.println(queue);
        System.out.println(queue.size());
        System.out.println(queue.isEmpty());
    }

}

result:

猜你喜欢

转载自blog.csdn.net/hexiaodiao/article/details/103512999