队列
1. 队列的概念
- 队列和链表来说非常的相似的,队列同样是前一个节点连接后一个节点,同样是线性结构;但是队列不同与链表的就是队列只允许尾部插入(入队),头部删除(出队),而链表是允许所有位置的操作,所以队列的情况与操作相对于链表要简单所以在这里我们就不再详细的解释普通队列的实现(需要实现的话可以在我上次写的链表操作中只留下尾部插入的代码即可)
循环队列
- 概念:对于队列来说循环队列才是需要注意 情况,他提高内存的利用效率同时也更加难以实现。循环队列相当于把队列的头和尾连接起来,用一个指针标记头结点的位置,这样头结点就不是固定可以在循环队列上面到处移动,只需要记住标记的位置就可以和队列中元素的个数就可以实现队列循环操作。
单循环队列
1. 基本实现
- 对于单循环队列实现我们依靠数组来是实现,使用front标记头结点的索引位置,然后通过计算得到尾结点的索引位置(具体到相应方法时会说明相应的计算方法),对于数组来说front头节点,所以只要出队我们就把front记录的索引后移一位,然后长度减一。如果刚好在数组的最后一个索引的位置是头结点front,那么我们进行出对操作之后,头节点front就应该移动到数组的起始索引位置从新开始计算,添加元素也是一样的操作,如果循环队列满了的话,我们就需要扩容(操作和动态数组是一样的)
2. 代码实现
- 获取真实索引:由于我们是在使用动态数组模拟一个循环队列操作,所以我们需要得到一个元素在数组的真实索引,并且把对应到循环数组的位置上去。下面我们用一个栗子来讲解,当前队列存在两个元素,而且存在当前数组的末尾,现在我们还想再添加一个元素,那么应该添加到那儿?我们认为这个动态数组其实是一个循环队列,所以我们也就可以想象他是首尾相连的,那么这样我们添加的下一个元素就是添加在数组的开头位置;这是我们直接看出来的,对于代码的操作来说他只是在队列的末尾进行添加操作,而不会去关系到底应该加到那一个位置,所以我们需要找到当前添加节点与数组索引的对应关系,而这个关系可以使用一个公式来得到头结点索引 + 当前队列长度 / 整个数组的长度得到的就是我们新插入元素的真实索引位置。
![添加](https://i-blog.csdnimg.cn/blog_migrate/19ed833142f2053e4e93ecc6dc16fa34.png)
private int index(int index) {
int x = index+front;
return x - ((x > elements.length) ? elements.length : 0);
}
- 添加元素:对于添加元素来说,就是在队列的末尾添加元素,对应到数组索引是0开始就是往队列size的位置添加元素,所以我们就把size传入index()函数中,去计算真实的索引位置。(出队操作,就是把传入的值设定为1就行了,因为队列都是从头出对,所以都是第一个元素出队)
public void enQueue(E e) {
ensureCapacity(size + 1);
elements[index(size)] = e;
size++;
}
public class CircleQueue<E> {
private int front;
private int size;
private E[] elements;
private static final int DEFAULT_CAPACITY = 10;
public CircleQueue() {
elements = (E[]) new Object[DEFAULT_CAPACITY];
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void enQueue(E e) {
ensureCapacity(size + 1);
elements[index(size)] = e;
size++;
}
public E deQueue() {
E e = elements[front];
elements[front] = null;
front = index(1);
size--;
return e;
}
public E front() {
return elements[front];
}
public void ensureCapacity(int capacity) {
int oldCapacity = elements.length;
if (oldCapacity >= capacity) return;
int newCapacity = oldCapacity + (oldCapacity >> 1);
E[] newElements = (E[]) new Object[newCapacity];
for (int i=0; i<size; i++) {
newElements[i] = elements[index(i)];
}
elements = newElements;
front = 0;
}
private int index(int index) {
int x = index+front;
return x - ((x > elements.length) ? elements.length : 0);
}
}