写一个环形队列

2019-06-18  本文已影响0人  无聊之园

背景:有一个人接收到的一个面试题,说写一个环形队列。

其实它描述的并非环形队列,而是普通的ArrayQueue。

先贴代码.
这里,队列空,dequeue会报错,队列满,enqueue会报错。
你会发现,这个跟arrayQueue,几乎一样,看起来是环形的结构,但是总感觉不对劲。
而且,你去看arrayQueue的源代码,会发现,思想几乎一样。。。
只是,少了arrayQueue的扩容机制。

public class DiyArrayQueue implements Queue {

    private static final int MAX_ARRAY_SIZE = 65536;

    private Object[] items;

    // 头节点,get的位置
    private int front;

    // 尾节点,put的位置
    private int rear;

    public DiyArrayQueue(int initQueueSize){
        // 容量+1,因为,尾节点永远不会追上头节点,也就是实际容量少了1.
        items = new Object[initQueueSize + 1];
        this.rear = 0;
        this.front = 0;
    }


    @Override
    public boolean enqueue(Object o) {
        int tmp = rear;
        if(++tmp == items.length){
            tmp = 0;
        }
        if(tmp == front){
            throw new RuntimeException("队列是满的");
        }
        rear = tmp;
        items[rear] = o;
        return true;
    }

    @Override
    public Object dequeue() {
        if(rear == front){
            throw new RuntimeException("队列是空的");
        }
        int tmp = front + 1;
        if(tmp == items.length){
            tmp = 0;
        }
        Object o = items[tmp];
        if(o == null){
            return null;
        }
        front = tmp;
        return o;
    }

    @Override
    public int size() {
        if(rear == front){
            return 0;
        }
        int size = rear - front;
        if(size < 0){
            return items.length - front + rear;
        }
        return size;
    }
}

我觉得,要环形队列,最起码,应该是会一直循环的吧,比如,可以一直enqueue。
像这样:
虽然我觉得这样也不对。

public class CircleQueue implements Queue {

    private static final int MAX_ARRAY_SIZE = 65536;

    private Object[] items;

    // 头节点,get的位置
    private int front;

    // 尾节点,put的位置
    private int rear;

    public CircleQueue(int initQueueSize){
        items = new Object[initQueueSize];
        this.rear = 0;
        this.front = 0;
    }


    @Override
    public boolean enqueue(Object o) {
        if(++rear == items.length){
            rear = 0;
        }
        items[rear] = o;
        return true;
    }

    @Override
    public Object dequeue() {
        int tmp = front + 1;
        if(tmp == items.length){
            tmp = 0;
        }
        Object o = items[tmp];
        if(o == null){
            return null;
        }
        front = tmp;
        // 设置空
        items[tmp] = null;
        return o;
    }

    @Override
    public int size() {
        // 空和full这两个指针都是指向相同的元素
        if(rear == front){
            // 如果有一个元素为null,则说明null的
            if( null == items[0]){
                return 0;
            }
            return items.length;
        }
        int size = rear - front;
        if(size < 0){
            return items.length - front + rear;
        }
        return size;
    }
}

总结:
1、这种数据结构,必须要定位使用场景,否则,很容易出现误解。
比如环形队列在延迟队列中得使用,就会是另一个环形队列得数据结构了。
2、而且,比如,有时候环形队列用链表会更合适,没有扩容得烦扰什么的。

上一篇 下一篇

猜你喜欢

热点阅读