循环队列
队列的顺序结构本身是由ArrayList实现的
在数据元素入队的时候,相当于在ArrayList表尾添加元素
在数据元素出队的时候,相当于在ArrayList表头删除元素
很明显,入队的时间复杂度O(1),出队的时间复杂度是O(n)
但是线性表的增删数据元素时间复杂度都是O(n),但是这个是按平均算的
优化一:
能否让队头指针和队尾指针一样随着数据元素的变化而变化呢
循环队列ArrayLoopQueue(该循环队列的实现思想是动态数组),但是由于操作元素的特殊性,并不能直接由ArrayList和ArrayQueue实现,所以从头开始定义ArrayLoopQueue
优化2:
队尾或者队头指针到达尾部,如需后移可以重新指向表头(可以继续循环)
优化三:
将一个空间留出来,专门放尾部指针
ArrayLoopQueue类
package 动态数组;
import 接口.Queue;
import java.util.Iterator;
public class ArrayLoopQueue<E> implements Queue<E> {
//定义队列默认的容量
private static int DEFAULT_CAPACITY;
//定义头指针
private int front;
//定义尾指针
private int rear;
//定义队列的有效元素的个数
private int size;
//定义队列的容器
//如果front==rear表示队列已空,
//如果(rear+1)%data.length==front表示队列已满
private E [] data;
//创建用户指定容量的队列
public ArrayLoopQueue(int capacity){
//加一是因为留一个空位置专门放尾指针
data =(E [])new Object[capacity+1];
front =0;
rear =0;
size =0;
}
//创建系统默认的容量的容器
public ArrayLoopQueue(){
this(DEFAULT_CAPACITY+1);
}
//获取循环队列有效元素的个数
@Override
public int size() {
return size;
}
//判断循环队列是否为空
@Override
public boolean isEmpty() {
return size==0&&front==rear;
}
//向循环队列中入队一个元素
@Override
public void offer(E element) {
data[rear]=element;
//表示下一个rear的位置,因为不能写成rear+1,因为这是一个循环的队列,所以用(rear+1)%data.length
rear=(rear+1)%data.length;
size++;
//判断是否需要扩容
if((rear+1)%data.length==front){
减一是因为我们要达到21的效果
resize(data.length*2-1);
}
}
//扩容
private void resize(int len) {
E [] newData =(E [])new Object[len];
int index=0;
for(int i=front;i!=rear;i=(i+1)%data.length){
newData[index++]=data[i];
}
//首尾指针需要重新改变
front=0;
rear=index;
data=newData;
}
//循环队列出队一个元素
@Override
public E poll() {
if(isEmpty()){
throw new NullPointerException("队列是空的");
}
E ret =data[front];
front =(front+1)%data.length;//表示下一个元素的位置
size--;
//判断是否要进行缩容
if(size==(data.length-1)/4&&data.length-1>DEFAULT_CAPACITY){
resize(data.length/2+1);
}
return ret;
}
@Override
public E element() {
if(isEmpty()){
throw new NullPointerException("队列是空的");
}
return data[front];
}
@Override
public void clear() {
data =(E [])new Object[DEFAULT_CAPACITY+1];
front =0;
rear =0;
size =0;
}
//重写toString()函数
public String toString(){
StringBuilder sb =new StringBuilder(String.format("ArrayLoopQueue:%d/%d[",size,data.length));
if(isEmpty()){
sb.append(']');
}
else{
for(int i=front;i!=rear;i=(i+1)%data.length){
sb.append(data[i]);
if((i+1)%data.length==rear){
sb.append(']');
}
else{
sb.append(',');
}
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return new ArrayLoopQueueIterator();
}
class ArrayLoopQueueIterator implements Iterator<E>{
//设置游标
private int cur=0;
@Override
public boolean hasNext() {
return cur!=rear;
}
@Override
public E next() {
E ret =data[cur];
cur=(cur+1)%data.length;
return ret;
}
}
}
测试类
package 动态数组;
public class TestArrayLoopQueue {
public static void main(String[] args) {
ArrayLoopQueue<Integer> loopQueue =new ArrayLoopQueue<>();
for(int i=0;i<=12;i++){
loopQueue.offer(i);
}
System.out.println(loopQueue);
}
}