队列(queue):又叫先进先出表,它是一种运算受限的线性表。
其限制是仅允许在表的一端进行插入和另一端取数据。
插入数据的一端是队尾,取数据的一端则是队头。
上图指出了顺序队列存储结构的不足——假溢出:
随着出队操作,front指针后移,当队尾有元素入队的时候,rear指针则移动到数组之外,但是此刻可以很明显的看到数组的空间并没有真正的利用完全,这就是假溢出。
如何解决假溢出?
- 按最大可能的进队操作次数设置顺序队列的最多元素个数,比如说如果要操作16次,则可以存储8个元素;但是这个方法很浪费空间,一般不用这个方法;
- 修改出队操作算法,使每次出队后都把队列中剩余的操作元素向队头移动一个位置;
- 修改入队算法,增加判断条件,当发生“假性溢出”时,把数据元素向队头移动;
- 采用循环队列;
本文代码实现采用第二种方式,当进行出队操作时,将后面的元素往前移动一个位置。
import java.util.Arrays;
/**
* @author lichen
* @version 1.0.0
* @date 2020-05-13 9:13
*/
public class MyQueue {
Object[] elements;
int currentSize;
int rear;
public MyQueue(int queueSize) {
elements = new Object[queueSize];
}
public void enqueue(Object data) throws Exception {
if (currentSize < elements.length) {
elements[rear] = data;
currentSize++;
rear++;
} else {
throw new Exception("队列已满");
}
}
public Object dequeue() {
if (currentSize == 0) {
return null;
}
Object data = elements[0];
// 元素往前移动
System.arraycopy(elements, 1, elements, 0, elements.length - 1);
currentSize--;
rear--;
// GC回收掉重复的元素
elements[rear] = null;
return data;
}
public int size() {
return currentSize;
}
public boolean isEmpty() {
return currentSize <= 0;
}
public static void main(String[] args) throws Exception {
MyQueue myQueue = new MyQueue(10);
System.out.println(myQueue.isEmpty());
myQueue.enqueue(48);
myQueue.enqueue(45);
myQueue.enqueue(46);
myQueue.enqueue(47);
myQueue.enqueue(47);
System.out.println(myQueue.isEmpty());
myQueue.enqueue(47);
myQueue.enqueue(47);
myQueue.enqueue(47);
myQueue.enqueue(47);
myQueue.enqueue(47);
Object dequeue = myQueue.dequeue();
Object dequeue1 = myQueue.dequeue();
Object dequeue2 = myQueue.dequeue();
Object dequeue3 = myQueue.dequeue();
System.out.println(dequeue);
System.out.println(dequeue1);
System.out.println(dequeue2);
System.out.println(dequeue3);
System.out.println(Arrays.toString(myQueue.elements));
System.out.println(myQueue.size());
}
}