队列和循环队列
循环队列相对于队列特点在于出队时队内元素不用依次移位,多维护了两个变量front和tail,front指向队首而tail指向队尾元素。
循环队列图示操作
- 循环队列为空的情况
front==tail
- 循环队列入队操作
每添加一个元素,tail往后挪一个位置
下图会告诉你为什么叫循环队列
- 循环队出队操作
删除一个元素,更新front对应的索引,注意这里不需要将后面的元素往前依次挪位
-循环列队满元素状态
如果再添加元素会front=tail,而这是循环队列为空的条件
(tail+1)%array.length==front
循环队列java代码实现
现在一起来实现一下循环队列吧!
循环队列的基本操作有:
-
入队方法
void enqueue(E element) -
出队方法并返回出队的元素
E dequeue() -
为空判断
boolean isEmpty() -
返回循环队列中的元素个数
int getSize() -
返回循环队列的容量
int getCapacity() -
返回循环队列队首元素
getFront()
public class LoopQueue<E> {
private E[] data;
private int front;
private int tail;
private int size;
public LoopQueue(int capacity){
// 因为浪费了一个空间,所以要在用户以为的容量上加上1
data=(E[])new Object[capacity+1];
front=0;
tail=0;
size=0;
}
public LoopQueue() {
this(10);
}
// 入队操作
public void enqueue(E element){
// 添加操作前对循环队列是否满进行判断
if((tail+1)%data.length==front){
resize(getCapacity()*2);
}
data[tail]=element;
tail=(tail+1)%data.length;
size++;
}
// 出队操作
public E dequeue(){
if(isEmpty()){
throw new IllegalArgumentException("不能对空队列进行出队操作");
}
// rem=remain
E rem=data[front];
//对象数组存储的是引用,这一步操作不至于使存储的引用所指向的对象一直占用空间
data[front]=null;
front=(front+1)%data.length;
size--;
if(size==getCapacity()/4 && getCapacity()/2!=0){
resize(getCapacity()/2);
}
return rem;
}
private void resize(int newcapacity) {
// 扩容操作,在新的数组中令front元素移至index=0的位置
E[] newData=(E[])new Object[newcapacity+1];
// 两种方式遍历循环队列之一,i<size,而不是getCapacity
for (int i = 0; i < size; i++) {
newData[i]=data[(i+front)%data.length];
}
front=0;
tail=size;
data=newData;
}
public boolean isEmpty(){
return front==tail;
}
public int getSize(){
return size;
}
public int getCapacity(){
return data.length-1;
}
public E getFront(){
if(isEmpty()){
throw new IllegalArgumentException("队列是空的");
}
return data[front];
}
@Override
public String toString(){
StringBuilder buffer=new StringBuilder();
// String.format格式化的字符串
buffer.append(String.format("Queue:size=%d ,capacity=%d\n",size,getCapacity()));
buffer.append("front [");
// 两种方式遍历循环队列之二
for (int i = front; i!=tail ; i=(i+1)%data.length) {
buffer.append(data[i]);
if((i+1)!=tail){
buffer.append(", ");
}
}
buffer.append("] tail");
return buffer.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);
}
}
}
}