循环队列:解决数组队列出队的时间复杂度

思路分析:

1.记录数组的队首和队尾的位置,当front 和tail指在一起的时候数组为空。

2.出队的时候front指针往后挪一位。这样出队操作就由数组队列的 O(N) 变成  循环队列的O(1)了。

让数组循环利用起来:

当前索引+1 再百分之我们数组的长度    比如我们到了最后一位7, 7+1 = 8 就是我们数组的长度    8对8 求余 = 0   

就跟钟表一样   找到它的范围  然后让它在范围内循环。    1%12 = 1;  2 % 12 = 2; .... 11%12=11 12%12 = 0  这样就能无限在范围内循环。

然而有一个问题我们front = tail 表示空数组,也可以表示满数组。为了达到区分我们要刻意浪费一个空间,tail+1 = front = 满数组!! 

 

package com.dapeng.Queue;
/**
 * @author gdp
 * @date 2020/4/5 23:06
 */
public class LoopQueue<E> implements Queue<E> {
    private E[] data;
    private int  front, tail; //数据首位   front==tail的时候空数组 但是也代表数组满了 所以我们设计为tail+1 为数组满了有意的浪费一个空间来做出区分
    private int size; //数组数据个数

    public LoopQueue(int capacity){
        data = (E[]) new Object[capacity+1]; //满足了用户需求也满足了程序设计
        front = 0 ;
        tail = 0 ;
        size = 0 ;
    }

    public LoopQueue(){
        this(10);
    }

    public  int getCapacity(){ return data.length -1; }
    @Override
    public boolean  isEmpty(){ return front == tail;}

    @Override
    public   int getSize(){ return size;}
    @Override
    public void enqueue(E e){
         //最后一个元素+1  取模
        if( (tail + 1) % data.length == front )
            resize(this.getCapacity() * 2 );

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

    @Override
    public E dequeue(){
        if(isEmpty()) throw new IllegalArgumentException("Cannot dequeue from  an  empty queue.");
        E ret  = data[front];
        data[front] = null;
        front =  (front +1) % data.length;
        size --;
         if(size  == this.getCapacity() /  4 && getCapacity()/2 != 0)
         {
             resize(getCapacity() / 2);
         }
        return ret;
    }

    @Override
    public E getFront(){
        if(isEmpty()) throw new IllegalArgumentException("  Queue is empty !.");
        return data[front];
    }

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

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



    public static void main(String[] args) {
        LoopQueue<Integer> queue = new LoopQueue<>();
        for(int i = 0 ; i < 10 ; i++ ){
            queue.enqueue(i);

   /*         if(i % 3 == 2){
                queue.dequeue();
                System.out.println(queue);
            }*/
        }
        System.out.println(queue.toString());
    }


}

这个是测试两种队列效率的代码:显然循环队列是快了很多的。

package com.dapeng.Queue;
import java.util.Random;
/**
 * @author gdp
 * @date 2020/4/6 18:41
 */
public class queueTest {
   private static double test(Queue<Integer> queue, int opCount){
       long startTime = System.nanoTime();
       Random random = new Random();
       for (int i = 0; i< opCount ; i++) queue.enqueue(random.nextInt(Integer.MAX_VALUE));
       for (int i = 0; i< opCount ; i++)  queue.dequeue();
       long endTime = System.nanoTime();

       return (endTime - startTime) / 100000000.0;
   }

    public static void main(String[] args) {
        int     opCount = 1000000;
        ArrayQueue<Integer> arrayQueue = new ArrayQueue<>();
        double time1 = test(arrayQueue, opCount);
        System.out.println("ArrayQueue, time:" +time1+"  s");

        LoopQueue<Integer> LoopQueue = new LoopQueue<>();
        double time2 = test(LoopQueue, opCount);
        System.out.println("LoopQueue, time:" +time2+"  s");
    }

}

两个耗时结果比较:

ArrayQueue, time:2926.524975 s
LoopQueue, time:0.457739 s

文章视频链接:https://www.ixigua.com/i6815911054443282948/

猜你喜欢

转载自www.cnblogs.com/study-gdp/p/12705223.html