4、循环队列

内容来自刘宇波老师算法与数据结构体系课

1、循环队列

上次基于动态数组实现的队列,出队是 O(n) 级别的,性能不高,这里用另外一种思路来实现队列

使用两个变量 front 和 tail,分别代表数组第一个元素的索引和最后一个元素的后一个索引
使用 data[front] 出队,data[tail] 入队
队列为空:size == 0
队列为满:size == length
/**
 * 循环队列
 * 使用 size, 不浪费空间
 * 队列为空: size == 0
 * 队列为满: size == length
 */
public class LoopQueue<E> implements Queue<E> {

    private E[] data;
    private int front;
    private int tail;
    private int size;

    public LoopQueue(int capacity) {
        data = (E[]) new Object[capacity];
        front = tail = size = 0;
    }

    public LoopQueue() {
        this(10);
    }

    @Override
    public void enqueue(E e) {
        if (size == data.length) resize(data.length * 2);

        data[tail] = e;
        tail = (tail + 1) % data.length;
        size++;
    }

    @Override
    public E dequeue() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        
        E ret = data[front];
        data[front] = null;
        front = (front + 1) % data.length;
        size--;
        
        if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
        return ret;
    }

    @Override
    public E getFront() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        return data[front];
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    public int getCapacity() {
        return data.length;
    }

    /**
     * 动态数组
     */
    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newData[i] = data[(i + front) % data.length];
        }
        data = newData;
        front = 0;
        tail = size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("LoopQueue2: size = %d, capacity = %d\n", size, getCapacity()));
        sb.append("Front [");
        for (int i = 0; i < size; i++) {
            sb.append(data[(i + front) % data.length]);
            if (i != size - 1) sb.append(", ");
        }
        sb.append("] Tail");
        return sb.toString();
    }
}

2、双端队列

/**
 * 双端队列
 * 使用 size, 不浪费空间
 * 队列为空: size == 0
 * 队列为满: size == length
 */
public class Deque<E> {

    private E[] data;
    private int front;
    private int tail;
    private int size;

    public Deque(int capacity) {
        data = (E[]) new Object[capacity];
        front = tail = size = 0;
    }

    public Deque() {
        this(10);
    }

    public void addFront(E e) {
        if (size == data.length) resize(data.length * 2);

        front = (front != 0) ? (front - 1) : (data.length - 1);
        data[front] = e;
        size++;
    }

    public void addLast(E e) {
        if (size == data.length) resize(data.length * 2);

        data[tail] = e;
        tail = (tail + 1) % data.length;
        size++;
    }

    public E removeFront() {
        if (isEmpty()) throw new RuntimeException("队列为空");

        E ret = data[front];
        data[front] = null;
        front = (front + 1) % data.length;
        size--;

        if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
        return ret;
    }

    public E removeLast() {
        if (isEmpty()) throw new RuntimeException("队列为空");

        tail = (tail != 0) ? (tail - 1) : (data.length - 1);
        E ret = data[tail];
        data[tail] = null;
        size--;

        if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
        return ret;
    }

    public E getFront() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        return data[front];
    }

    public E getLast() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        return (tail != 0) ? data[tail - 1] : data[data.length - 1];
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public int getSize() {
        return size;
    }

    public int getCapacity() {
        return data.length;
    }

    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newData[i] = data[(i + front) % data.length];
        }
        data = newData;
        front = 0;
        tail = size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("Deque: size = %d, capacity = %d\n", getSize(), getCapacity()));
        sb.append('[');
        for (int i = 0; i < getSize(); i++) {
            sb.append(data[(i + front) % data.length]);
            if (i != getSize() - 1) sb.append(", ");
        }
        sb.append(']');
        return sb.toString();
    }
}
posted @ 2023-04-10 14:27  lidongdongdong~  阅读(11)  评论(0编辑  收藏  举报