LoopQueue
Code:
package dataStucture2.stackandqueue; /** * 循环队列 * * @param <E> */ public class MyLoopQueue<E> implements Queue<E> { /* * 成员变量:泛型数组、两个指向变量、循环队列个数size */ private E[] data; private int front, tail; private int size; // 有参构造,初始化数组容量大小,指向变量指向索引为0 public MyLoopQueue(int capacity) { // 判断tail在front前一位时队列为满,为了达到用户要求的容量,要求capacity比默认大1,此时多出的一位用于判断队列为满 //实际长度:capacity+1 可用长度:capacity data = (E[]) new Object[capacity + 1]; front = 0; tail = 0; size = 0; } // 无参构造,默认容量为10 public MyLoopQueue() { this(10); } // 获取循环队列容量 ,1的存在为了判断队列为满,并不存储元素,此处减去 int getCapacity() { //实际长度:capacity+1 可用长度:capacity return data.length - 1; } @Override // front和tail指向同一个位置,循环队列为空 public boolean isEmpty() { return front == tail; } @Override // 获得循环队列元素个数 public int getSize() { return size; } @Override //入队 public void enqueue(E e) { //首先判断队列是满,如果满了,进行扩容 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 empty queue ! "); } //如果不为空,出队 E ret = data[front]; data[front] = null; front = (front + 1) % data.length; size -- ; //动态扩容 if(size == getCapacity() / 4 && getCapacity() / 2 != 0) resize(getCapacity() / 2); return ret; } @Override //获取队首元素 public E getFront() { if(isEmpty()){ throw new IllegalAccessError("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 ++){ //循环队列,%data.length为了防止越界 newData[i] = data[( i + front ) % data.length]; } /** * 此处错误:不应当每次扩容遍历都resize,遍历的目的是复制元素到新的数组,复制完了原数组指向新的数组完成扩容 */ data = newData; front = 0; tail = size; } @Override //打印循环队列 public String toString() { StringBuilder res = new StringBuilder(); res.append(String.format("Queue: size = %d , capacity = %d\n", size , getCapacity())); res.append("front ["); //遍历循环队列,和resize中的循环遍历是两种方式,都可以达到母的 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(); } }
循环队列解决了普通队列出队复杂度为O(n)的问题
toString方法和resize方法中,遍历循环队列的异同
循环队列的简单时间复杂度分析: