如何利用循环数组构建队列

队列(FIFO)也就是一种先进先出的数据结构,它有很多种实现方式,链表、数组,下面讲的就是如果利用循环数组来实现队列。

如果利用单纯的利用数组 它的出队 (后面的数组都要向前移动)时间复杂度是O(n),但是如果把数组实现成一个循环的数组

出队时 front加一就好了 后面的数组不必一一向前移动,那么他的时间复杂度就可以变为O(1),下面就直接撸代码

public class LoopQueue<E> {
    private E[] data;
    private int front;//表示队首头部的索引
    private int tail;//表示队尾的索引
    private int size;//表示数据的大小
    public LoopQueue(int capacity){
        //数组的容量 多出一个 不存任何数组 因为用它来区分 空 和 数组满的两种情况 当tail == front表示数组为空           
        (tail+1)%data.legth == front 表示数组满了
        data = (E[]) new Object[capacity+1];
    }

    public LoopQueue(){
        this(10);
    }

    public int getCapacity(){
       //真正的数据容量也就是数组长度减一 因为预留出一个位置什么也不存
        return data.length-1;
    }

    public boolean isEmpty(){
       //表示数组为空
        return front == tail;
    }

   public boolean isFull(){
       //这里就提现出那个预留一个位置不存任何数组位置的作用了  这里就表示数组满了
       return (tail+1)%data.length == front;
   }

    public void enqueue(E e){
       //数组满了  需要扩容了 这次每次扩容 为原数组容量的2倍
        if((tail+1)%data.length == front){
            resize(getCapacity()*2);
        }
       //在数组尾部添加一个元素
        data[tail] = e;
      //tail加一   因为这是一个循环数组  所以要进行取模
        tail = (tail+1)%data.length;
      //数组长度加一
        size++;

    }


    public void resize(int newCapacity){
       //这里同样多加了一个数组空间  用了什么也不存
        E[] newData = (E[]) new Object[newCapacity+1];
        for(int i=0;i<size;i++){
           //data 数组是从 front开始的  记得取模  因为他是一个循环  然后复制给新的数组
            newData[i] = data[(front+i)%data.length];
        }
        //那么现在的tail位置就是数组长度位置
        tail = size;
       //front 从0开始  因为把它重新复制给了一个新的数组
        front = 0;
        data = newData;


    }


    public E dequeue(){
       //取出队首数组
        E e = data[front];
        //取出之后  font就要进行+1  因为他是一个循环所以要进行加一取模
        front = (front+1)%data.length;
       //数组大小减-
        size--;
       // 如果数组长度为容量的1/4时候 且容量长度除2不为0 那么就重新缩容。  这里为什么在数组长度为容量1/4的时候进行缩容呢而不    是1/2呢,这里是有原因的  如果当数组为1/2的时候缩容,然后添加一个数据  然后有扩容,又删除一个数据缩容,复杂度就会进行震荡而1/4的时候 缩容为数组的1/2很好的错开了这个加一扩容 减一缩容的时间复杂的震荡

        if(size == getCapacity()/4 && getCapacity()/2!=0){
            resize(getCapacity()/2);
        }
        return e;
    }


    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("capacity %d size %d front\n[", getCapacity(), size));
        for(int i=front;i != tail;i = (i+1)%data.length){
            builder.append(data[i]);
            if((i+1)%data.length != tail){
                builder.append(",");
            }
        }
        builder.append("]");
        return builder.toString();
    }
}
发布了27 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u013297345/article/details/102685949
今日推荐