队列
public class MyQueue<T> {
public MyQueue(int capacity) {
this.capacity = capacity + 1;
this.queue = newArray(capacity + 1);
this.head = 0;
this.tail = 0;
}
/**
* 重新按照新的size来调整数组
* @param newcapacity
*/
public void resize(int newcapacity) {
//先判断先的容量是否能够容纳现在已有的数据
int size = size();
if (newcapacity < size)
throw new IndexOutOfBoundsException("Resizing would lose data");
//如果和现有长度一样,则不需要重新移动数据到新创建的数组
newcapacity++;
if (newcapacity == this.capacity)
return;
T[] newqueue = newArray(newcapacity);
//移动数据到新的数组
for (int i = 0; i < size; i++)
newqueue[i] = get(i);
this.capacity = newcapacity;
this.queue = newqueue;
this.head = 0;
this.tail = size;
}
@SuppressWarnings("unchecked")
private T[] newArray(int size) {
return (T[]) new Object[size];
}
/**
* 新增队列元素
* @param o
* @return
*/
// 看现有元素是否超过数组的长度,% 若是a%b a小则结果为a,a大则为a/b的余数
//如果刚好加上这个元素之后刚好a%b =0 也就是a==b的时候,就是队列满了的时候
public boolean add(T o) {
queue[tail] = o;
int newtail = (tail + 1) % capacity;
if (newtail == head)
throw new IndexOutOfBoundsException("Queue full");
tail = newtail;
return true; // we did add something
}
public T remove() {
// 如果队头遇到队尾了,也就是队列空了
if (head == tail)
throw new IndexOutOfBoundsException("Queue empty");
T removed = queue[head];
//删去队头的值
queue[head] = null;
//重新定义队头位置
head = (head + 1) % capacity;
//把删除的队头元素返回
return removed;
}
/**
* 获取
* @param i
* @return
*/
public T get(int i) {
int size = size();
//先判断是否是超过了队列的元素个数,或者是个负数
if (i < 0 || i >= size) {
final String msg = "Index " + i + ", queue size " + size;
throw new IndexOutOfBoundsException(msg);
}
//感觉这一步也是有点多余,因为在上一步已经判断了是否超过了队列的元素个数了,为啥还要%
int index = (head + i) % capacity;
return queue[index];
}
/**
* 获取当前元素个数
* @return
*/
public int size() {
// Can't use % here because it's not mod: -3 % 2 is -1, not +1.
int diff = tail - head;
//为啥diff会有<0 的情况呢? 队尾比队头小?
if (diff < 0)
diff += capacity;
return diff;
}
// 当前队列的容量
private int capacity;
//装数据的数组
private T[] queue;
//当前队头的位置
private int head;
//当前队尾的位置
private int tail;
}