队列是先进先出(这里考虑单向队列),队尾进栈,队头出站,当队头指针等于队尾指针时,表示队列里面已经没有元素了,不能再进行出队操作了,当队尾指针等于队列长度时,需要进行扩容(这里并不是需要真正的扩容,下面代码实现的是一种扩容).
public class MyQueue<T> {
private Object[] t; //这里声明为Object而不声明为T,是因为下面需要对数组进行实例化,而泛型不能new
private int capacity = 0; //数组容量,扩容的大小
private int popIndex = 0; //出队指针
private int pushIndex = 0; //入队指针
public MyQueue(){
this(6); //默认声明数组为6
}
public MyQueue(int capacity){
this.capacity = capacity;
this.t = new Object[capacity];
}
/**
* 出队,当出队指针大于入队指针时,表示已经没有元素了
* @return 队列还有元素时返回出队元素,队列没有元素就返回null
*/
public T pop(){
if (popIndex < pushIndex){
T pop = (T)this.t[popIndex]; //需要将Object强转为T
popIndex ++; //出队指针+1
return pop;
}
return null;
}
/**
* 入队,当队列还有空位置时,把元素写入队列,没有空元素时(这里指的是入队指针等于数组长度),进行扩容(扩容的改进下面讲)
* @param push
*/
public void push(T push){
if (pushIndex == t.length){
expansion();
}
this.t[pushIndex] = push; //入队
pushIndex ++; //入队指针+1
}
/**
* 扩容,上面写的当出队指针(pushIndex)等于数组长度(t.length)就进行扩容是有问题.
* 现在考虑一个场景,队列长度为6,先入队4个元素,此时popIndex=0,pushIndex = 4,出队4个元素,此时popIndex=3,pushIndex=4
* 再入队两个元素 popIndex=3,pushIndex=6,如果此时再入队元素,那么队列就会扩容,要是这样一直入队出队,那么就会一直扩容
* 这就会导致无限制增大,其实队列元素是没有占满的,但是也进行了扩容,这样就会有问题.
* 改进的方法就是允许进行一次扩容,当出队指针(popIndex)>6(初始容量时),不进行扩容,只进行数组的copy移动.
*/
private void expansion() {
int length = popIndex > capacity ? t.length : t.length+capacity;
Object[] tmp = new Object[length];
System.arraycopy(t,popIndex,tmp,0,pushIndex-popIndex);
t = tmp;
pushIndex = pushIndex-popIndex;
popIndex = 0;
}
public int length(){
return t.length;
}
public int getPopIndex() {
return popIndex;
}
public int getPushIndex() {
return pushIndex;
}
}