为了避免数组删除时候需要移动数据,引入了循环队列,解决了删除时候需要消耗大量时间的弊端,使得本来删除时的时间复杂度为O(n)(因为要移动数据)变成了O(1)。
这里的循环队列用数组来实现,以下是几个约定或者说是公式:
1、队列的队头指针指向队列的第一个元素,队列的队尾指针指向
队列的最后一个元素的下一个位置
2、数组剩下一个空位的时候,队列已满
3、队列为空的时候,数组front == rear,故初始化时,front
= rear = 0; (但在实际编程中会用length记录队列长度)
4、队满的公式是(rear+1)%size()==front;(但在实际编程中会用
length == size()-1判断队是否满)
5、队列长度公式(rear-front+size())%size();(但在实际编程中会用
length记录队列长度)
6、指针的移动:出队:front = (front+1)%size(); 入队:rear = (rear+1)%size()
7、注意获取队尾元素的方法
循环队列类:
package cn.test.queue;
/**
* 循环队列,用数组实现
* @author cjc
*
*/
public class MyCirculQueue<T> {
/**
* 几个约定:
* 1、约定数组剩下一个空位时候,队列已满
* 2、约定数组的front==rear时,队列为空 (但在实际编程中用length)
* 3、约定队头front指向队列的第一个元素,队尾rear执行队列的最后一个
* 元素的下一个位置
* 4、判断队满的公式(rear+1)%queueSzie==front
* 5、(可选)队列长度的公式(rear-front+queueSize)%queueSize(可以每
* 进入一个元素length++; 每出队一个元素length--)
* 6、出队:(front + 1) % queueSize
* 7、入队后,rear不再是单纯加1,而是rear = (rear + 1) % size();
*/
private T[] elements;
private int length;
private int front;
private int rear;
public MyCirculQueue(){
this(16);
}
//指定容量
public MyCirculQueue(int size) {
elements = (T[])new Object[size];
front = rear = 0;
}
public int getLength() {
return length;
}
public int size(){
return elements.length;
}
//队列是否为空
public boolean isEmpty(){
return length == 0;
}
//队列是否为满
public boolean isFull(){
return length == size() - 1; //留出一个空位
}
//入队操作
public boolean insert(T data){
if(isFull()){
System.out.println("队列已满");
return false;
}else{
elements[rear] = data;
rear = (rear + 1) % size();
length++;
return true;
}
}
public T delete(){
if(isEmpty()){
System.out.println("队列为空");
return null;
}else{
T retData = elements[front];
front = (front + 1) % size();
length--;
return retData;
}
}
//得到队头元素
public T getFront(){
return elements[front];
}
//得到队尾元素
public T getRear(){
if(0 == rear){
return elements[size()-1];
}else{
return elements[(rear-1)%size()];
}
}
//打印
public void print(){
int tmp = front;
while(tmp != rear){
System.out.print(elements[tmp] + " ");
tmp = (tmp + 1) % size();
}
System.out.println();
}
}