在数组队列中,由于删除元素内部会将元素整体前移一个位置,因此时间复杂度为O(n)
循环队列中通过维护头尾指针这种方式将删除元素的时间复杂度降为O(n)
判断队列是否为空
front ==tail
判断队列是否为满
(tail+1)%c == front
自定义一个循环队列
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front, tail;
private int size;
//因为判断是否为满的条件为(tail+1)%c==front会浪费一个空间,因此会开辟capacity+1的存储空间
public LoopQueue(int capacity) {
//循环队列会浪费一个空间
data = (E[]) new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
}
//默认10个空间
public LoopQueue() {
this(10);
}
//获取队列中元素的个数(循环队列会浪费掉一个空间)
@Override
public int getSize() {
return size;
}
public int getCapacity() {
return data.length - 1;
}
@Override
public boolean isEmpty() {
return front == tail;
}
@Override
//循环队列入队,判断是否为满,如果为满要进行扩容
public void enqueue(E e) {
if ((tail + 1) % data.length == front) {
resize(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 element =data[front];
data[front]=null;
front=(front+1)%data.length;
size--;
//当元素只占据容量的1/4空间缩容到原来的一半
if (size==getCapacity()/4&&getCapacity()/2!=0){
resize(getCapacity()/2);
}
return element;
}
@Override
public E getFront() {
if (isEmpty())
throw new IllegalArgumentException("Queue is empty");
return data[front];
}
//扩容 把原来的元素移动到新的队列,旧队列的首元素不一定为0,要看front的位置并且它是一个循环队列
private void resize(int newCapacity) {
E[]newData= (E[]) new Object[newCapacity+1];
for (int i=0;i<size;i++){
newData[i]=data[(i+front)%data.length];
}
data=newData;
front=0;
tail=size;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(String.format("Queue:size=%d,capacity=%d\n",size,getCapacity()));
stringBuilder.append("front[");
//循环队列中tail可能小于front
for (int i = front; i !=tail ; i=(i+1)%data.length) {
stringBuilder.append(data[i]);
//判断是否是最后一个元素
if ((i+1)%data.length!=tail)
stringBuilder.append(", ");
}
stringBuilder.append("]tail");
return stringBuilder.toString();
}
public static void main(String[] args) {
LoopQueue<Integer> queue = new LoopQueue<>();
for (int i=0;i<10;i++){
queue.enqueue(i);
System.out.println(queue);
if (i%3==2){
queue.dequeue();
System.out.println(queue);
}
}
}
}