队列
队列是一种先进先出的顺序存储结构,尾端进,头端出。这里我使用数组来实现队列。
思路分析
队列尾进头出,因此我们需要定义两个变量,相当于指针,分别指向队列的头部和尾部。定义一个数组,用来储存元素。我用front来表示头指针,但是指向的是队列头元素的前一个位置;用rear来表示尾指针,指向的是队列的尾元素。 并且将front和rear都赋值为-1。当头尾指针相等,指向同一块空间,即当rear == front时,队列为空。
图解
如果只是从模拟实现队列的功能来说确实是完成了,但是此时的队列也有个致命的缺点,下面结合代码演示。
代码
package com.zxb.queue;
public class Test<T> {
private T[] arr; // 定义一个数组模拟队列
private int front; // 定义头指针
private int rear; // 定义尾指针
public Test(int capacity) {
arr = (T[]) new Object[capacity];
front = -1;
rear = -1;
}
public boolean isEmpty() {
return front == rear; //当头尾指针相等,则为空
}
public boolean isFull() {
return rear == arr.length - 1; // 当尾指针指向队尾元素为满
}
public void add(T ele) { // 入队
if (isFull()) {
throw new RuntimeException("队列已满");
}
rear++; // 队列尾进头出,尾指针++,头指针仍等于-1,指向队头的前一个元素
arr[rear] = ele;
}
public T poll() { // 出队
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
front++; // 队列尾进头出,头指针++
return arr[front]; //返回出队的元素
}
public T getFront() { //获取队首元素
if (isEmpty()) {
throw new RuntimeException("对列空,不能取数据");
}
return arr[front + 1]; // front指向的是队首的前一位,故要+1
}
public T getRear() { //获取队尾元素
if (isEmpty()) {
throw new RuntimeException("对列空,不能取数据");
}
return arr[rear];
}
public String toString() { //打印队列元素
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int x = 0; x < arr.length; x++) {
sb.append(arr[x]);
if (x < arr.length - 1) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
public static void main(String[] args) {
Test<String> t = new Test<>(5);
t.add("Tom");
t.add("Jack");
t.add("Rose");
t.add("John");
t.add("Brown");
System.out.println("出队元素为:" + t.poll());
System.out.println("出队元素为:" + t.poll());
System.out.println("出队元素为:" + t.poll());
System.out.println("出队元素为:" + t.poll());
System.out.println("队首元素为:" + t.getFront());
System.out.println("队尾元素为:" + t.getRear());
}
}
运行结果为
当队列添加满时,我们出4次队,队列中还剩一个Brown,故他是头元素也是尾元素。看起来没问题,那么此时队列应该说是还有四个空位。于是我们再添加一个元素试试。
这时报错了,明明有着空位却无法添加,这种现象称之为“假溢出”。这是怎么导致的呢?
很简单,因为此时队列物理上还是满的。我们所说的空和满都是逻辑上的。就和逻辑地址一样,我们可以扩大逻辑地址,但无法扩大给定的物理地址。我们从头至尾都是对头尾指针进行操作,并没有对底层的数组进行修改,不像数组那样有size++和size–来维护数组的元素个数。 如果我们也给底层数组加上size来维护,那么就达不到模拟队列的功能了,因为数组添加和删除都在队尾进行。
那么为了解决这种问题,我们引入了循环队列这个概念。
朋友们要是觉得博客写的还行,可以看看我的循环队列哦。