标签:它的 queue gets cannot not i+1 个数 tca 数据
思路分析:
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 LoopQueueimplements Queue {
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 )
{
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 queue = new LoopQueue();
for(int i = 0 ; 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 queue, int opCount){
long startTime = System.nanoTime();
Random random = new Random();
for (int i = 0; i) queue.enqueue(random.nextInt(Integer.MAX_VALUE));
for (int i = 0; i) queue.dequeue();
long endTime = System.nanoTime();
return (endTime - startTime) / 100000000.0;
}
public static void main(String[] args) {
int opCount = 1000000;
ArrayQueue arrayQueue = new ArrayQueue();
double time1 = test(arrayQueue, opCount);
System.out.println("ArrayQueue, time:" +time1+" s");
LoopQueue 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/
循环队列:解决数组队列出队的时间复杂度
标签:它的 queue gets cannot not i+1 个数 tca 数据
原文地址:https://www.cnblogs.com/study-gdp/p/12705223.html