循环队列
队列:只允许在一端进行插入,另一端进行删除的线性表
循环队列:队列首尾相接的顺序存储结构称作循环队列。
队列顺序存储的不足:顺序存储我们一般使用数组,那么假设一个队列有n个元素,首先需要建立一个大于n的数组,把所有元素存入数组的前n个地址,每次删除完之后前面也就是队头所在的位置会空出来,无法继续利用,就需要所有元素向前移动,但这样时间复杂度为O(n).除此之外,如果数组长度为n,队头和队尾在n-1处,前面有n-2个空的地址,但是我们需要入队时会提示我们数组越界,这种现象叫做“假溢出”
要解决假溢出的方法就是后面满了就从头开始,也就是首位相连形成一个环,就是循环队列。
判队空就是 front == rear
队列大小的计算是(rear-front+MAXSIZE)%MAXSIZE,当rear>front时,队列长度是rear-front,当rear<front时,队列长度是,MAXSIZE-front和rear的和,就是rear-front+MAXSIZE,因此,通用的计算队列的长度公式为:(rear-front+MAXSIZE)%MAXSIZE。
循环队列的代码
简单的入队和出队操作
public class CircularQueue<T> {
private static final int MAXSIZE = 5; //
private T[] element;
private int front; //队首下标即队首指针
private int rear; //队尾下标即队尾指针
public CircularQueue(){
this(MAXSIZE);
}
public CircularQueue(int size){
element = (T[])new Object[size];
front = 0;
rear = 0;
}
//判队空
public boolean isEmpty(){
return front == rear;
}
//判队满
public boolean isFull(){
return rear+1 == front;
}
//队列大小
public int size(){
return (rear-front+MAXSIZE)%MAXSIZE;
}
//入队
public void offer(T value){
if (isFull()){
throw new ArrayIndexOutOfBoundsException();
}else{
element[rear] = value;
rear = (rear+1)%MAXSIZE; //到达最后一个以后转到数组头部
}
}
//出队
public T poll(){
if (isEmpty()){
throw new NullPointerException();
}else{
T data = element[front];
element[front] = null; //防止内存泄漏
front = (front+1)%MAXSIZE;
return data;
}
}
//获取队首元素
public T peek(){
if (isEmpty()){
throw new NullPointerException();
}else{
return element[front];
}
}
//打印队列元素
public void show(){
int temp = front;
while (temp != rear){
System.out.println(element[temp]);
temp++;
}
}
}