写在前面
学习了队列,就不得不知道一些特殊的队列,在实际应用中,这些队列有时用的更多,此为循环顺序队列
背景
对于一个容量为3的顺序存储的队列,先入队a,b,c然后出队a,b,c
此时,虽然队列中没有元素,但是显示的是队列已满,此时不能再存储数据,也就是出现了“假溢出” 现象,此时会造成存储空间的浪费
介绍
循环顺序队列就是为了防止出现假溢出现象而出现的,其功能类似于一个环形,如图,但实际上还是一个线性存储的结构
这样就不会出现“假溢出”的现象了,因为每次无论是出队还是入队时,移动指向队首和队尾元素的指针是循环变化的,也就是front=(front+1)%maxSizerear=(rear+1)%maxSize
面临的问题
随着而来的一个问题就是:空栈和满栈的条件都是front==rear
解决的方法有三个:
①少用一个存储空间:
空:front==rear
满:front==(rear+1)% maxSize
②设置一个标志变量(flag)记录是否有元素
空:front==rear&&flag==0
满:front==rear&&flag==1
③设置一个计数器(number)记录有多少个元素
空:number==0
满:number>0&&front==rear
代码描述
package org.Stone6762.MQueue.imple;
import org.Stone6762.MQueue.MQueue;
/**
* @ClassName_CircleSqQueue循环顺序队列---采用的是<span style="font-family: Arial;font-size:18px; line-height: 26px;">少用一个存储空间的方式</span>
* @author_Stone6762
*/
public class CircleSqQueue implements MQueue {
/**
* @queueElem存储队列中的元素
*/
private Object queueElem[];
/**
* @front指向队首
*/
private int front;
/**
* @rear指向队尾
*/
private int rear;
/**
* @Title构造器
*/
public CircleSqQueue(int maxSieze) {
this.front = this.rear = 0;
queueElem = new Object[maxSieze];
}
@Override
public void clear() {
front = rear;
}
@Override
public boolean isEmpty() {
return front == rear;
}
@Override
public int length() {
/*
* 因为rear-front有可能为负数,如果为负数,则其绝对值表示的是空的存储空间的个数(出现假溢出了),
* 加上maxSize,则就能求有多少元素.如果为正数,则其值直接就是队列中存储元素的个数
*/
return (rear - front + queueElem.length) % queueElem.length;
}
@Override
public Object peek() {
if (isEmpty()) {
return queueElem[front];
} else {
return null;
}
}
@Override
public void offer(Object data) throws Exception {
if((rear+1)%queueElem.length==front){//满了
throw new Exception("队列已满");
}else{
queueElem[rear]=data;
rear=(rear+1)%queueElem.length;
}
}
@Override
public Object poll() {
if (!isEmpty()) {
Object elem = queueElem[front];
front = (front + 1) % queueElem.length;
return elem;
} else {
return null;
}
}
public void disPlay() {
if (!isEmpty()) {
for (int i = front; i != rear; i = (i + 1) % queueElem.length) {
System.out.println(queueElem[i].toString() + " ");
}
} else {
System.out.println("队列为空!!!!!");
}
}
}