刚前一篇(
点击打开链接)也说到顺序队列存储时的问题,所以引出循环队列的解决方案。
因为前一篇也说到了队列的基本概念,所以这里使用图示和代码直接理解。
图示(制作简陋,请见谅):
此时可以看出来rear当满了之后,就转头从0开始,继续往后。但是此时如何判断它是满的状态?只根据rear == front有局限性。这里我是加了一个判断front处的数据元素值是不是等于null.
判断队列的长度:rear > front, 则len = rear - front。2.rear < front , 则len = size - (front - rear)。这里size是数组的大小。
此时是将它分为两端的0 - rear段 和 front - size。
参考代码:
public class LoopQueue<T> {
private int DEFAULT_SIZE = 20;
//记录数组的长度或者说容量
private int length;
//定义一个数组来存储这个队列的元素
private Object[] elementData;
//保存当前队列的个数
private int front = 0;
private int rear = 0;
//根据默认的长度构建一个顺序队列
public LoopQueue(){
this.length = DEFAULT_SIZE;
elementData = new Object[length];
}
//以一个初始元素建立顺序队列
public LoopQueue(T data){
this();
elementData[0] = data;
rear ++;
}
//以一个初始元素和指定的长度建立顺序队列 data相当于指定的第一个元素, initSize 指定顺序队列底层数组的长度
public LoopQueue(T data, int initSize){
this.length = initSize;
elementData = new Object[length];
elementData[0] = data;
rear ++;
}
//插入队列
public void insert(T data){
if(rear == front && elementData[front] != null){//对于循环队列 空和满均有rear == front
throw new IndexOutOfBoundsException("队列已满!");
}
elementData[rear++] = data;
//如果插满了rear要再次等于0
rear = rear == length ? 0 : rear;
}
//移除或者删除队列
public T remove(){
if(empty()){
throw new IndexOutOfBoundsException("空队列!");
}
//队列front端的元素值
T oldValue = (T)elementData[front];
//释放队列front端的元素
elementData[front++] = null;
//如果front到头了, 那就需要转头
front = front == length ? 0 : front;
return oldValue;
}
//判断是否为空队列
private boolean empty() {
return rear == front && elementData[rear] == null;
}
//循环获取队列大小
public int length(){
if(empty()){
return 0;
}
return rear > front ? rear - front : length - (front - rear);
}
//返回队头的元素
public T element(){
if(empty()){
throw new IndexOutOfBoundsException("空队列!");
}
return (T)elementData[front];
}
//清空队列
public void clear(){
//将底层的数组所有元素赋值为Null
Arrays.fill(elementData, null);
front = 0;
rear = 0;
}
public String toString(){
if(empty()){
return "[]";
}
else{
if(front < rear){
StringBuffer sb = new StringBuffer("[");
for(int i = front ; i < rear ; i ++){
sb.append(elementData[i].toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();
}
else{
StringBuffer sb = new StringBuffer("[");
for(int i = front ; i < length ; i ++){
sb.append(elementData[i].toString() + ", ");
}
for(int i = 0 ; i < rear ; i ++){
sb.append(elementData[i].toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();
}
}
}
}
这里大部分的思路和顺序队列相近,可以参照代码及注释,图示去推理。
测试部分及截图:
public static void main(String[] args) {
LoopQueue<String> lq = new LoopQueue<String>("aa", 4);
lq.insert("bb");
lq.insert("cc");
lq.insert("dd");
System.out.println(lq);
lq.remove();
System.out.println("此时的长度:" + lq.length());
lq.insert("ee");
System.out.println(lq);
System.out.println("此时的长度:" + lq.length());
}
参考:《疯狂java 突破程序员基本功的16课》
以上是这篇的大致内容,若有错误或需要改进的地方,请指教。谢谢!