Java实现循环队列(可以自动扩容)

Java实现循环队列(可以自动扩容)


先声明接口interface Queue<E>

//适用泛型
public interface Queue<E> {

	int getSize();
	boolean isEmpty();
	void enqueue(E e);//入队
	E dequeue();//出队
	E getFront();//获得队首元素
}

class LoopQueue<E>实现接口,测试也放在里面了

/**
 * @author yinglongwu
 */
//循环队列
public class LoopQueue<E> implements Queue<E> {
	
	private E[] data;
	private int front,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 int getCapacity() {
		return data.length-1;
	}

	//获取当前数组的元素个数
	@Override
	public int getSize() {
		return size;
	}

	//如果队首和队尾指向的位置相同则为空
	@Override
	public boolean isEmpty() {
		return front == tail;
	}

	//入队
	@Override
	public void enqueue(E e) {
		//队尾对队列的容量取余,使队列循环起来(+1就是浪费的一个空间用来判断是否满了)
		if ((tail+1)%data.length == front) {//如果循环队列满了
			resize(getCapacity()*2);//扩容
		}
		
		data[tail] = e;
		tail = (tail+1)% data.length;
		size++;
	}

	//出队
	@Override
	public E dequeue() {
		if (isEmpty()) {
			throw new IllegalArgumentException("Cannot dequeue from an enpty queue.");
		}
		
		E ret = data[front];
		//下面这句可加可不加,加上之后,java会自动回收,不加上就等下次这个位置指向新的对象,才回收这次的对象
		data[front] = null;//loitering objects != memory leak 闲逛的对象不等于内存泄漏。
		front = (front+1)%data.length;
		size--;
		//如果当前队列中元素个数等于数组的1/4,队列容量缩小1/2(减小复杂度震荡),可以节约空间
		if (size == getCapacity() / 4 && getCapacity()/2!=0) {
			resize(getCapacity()/2);
		}
		return ret;
	}

	//获取队首元素
	@Override
	public E getFront() {
		if (isEmpty()) {
			throw new IllegalArgumentException("Queue is empty.");
		}
		return data[front];
	}
	
	private void resize(int newCapacity) {
		
		E[] newData = (E[])new Object[newCapacity + 1];
		for(int i=0;i<size;i++) {
			//将原来的循环队列里的元素从队首开始,依次放到新循环队列里
			newData[i] = data[(i+front)%data.length];
		}
		
		data = newData;
		front = 0;
		tail = size;
	}
	
	//重写toString方法,可以更方便的显示队列信息
	@Override
	public String toString() {
		StringBuilder res = new StringBuilder();
		res.append(String.format("Queue: size = %d, capacity = %d\n",size,getCapacity()));
		res.append("front [");//表明队首
		for (int i = front; i != tail; i=(i+1)%data.length) {
			res.append(data[i]);
			//如果不是最后一个元素
			if ((i+1)%data.length != tail) {
				res.append(", ");
			}
		}
		res.append("] tail");//表明队尾
		return res.toString();
	}
	
	//测试
	public static void main(String[] args) {
		
		LoopQueue<Integer> queue = new LoopQueue<Integer>();
		for (int i = 0; i < 10; i++) {
			queue.enqueue(i);//入队
			System.out.println(queue);
			
			if (i%3==2) {//每三个元素出队一次
				queue.dequeue();
				System.out.println(queue);
			}
		}
	}
	
}

测试结果
在这里插入图片描述

发布了318 篇原创文章 · 获赞 44 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43594119/article/details/105319405