数据结构与算法之环形队列(以int数组为例,不包含扩容)
程序员文章站
2022-03-05 12:49:18
...
废话补不多说了, 环形队列最难理解的部分就是取模部分, 可以先看一下这个链接的大佬的讲解:
https://juejin.im/post/5c95d2515188252dab3ebfc5
如果上面这个链接的内容看懂了, 那本章的内容就不用看了, 就只当我做一个学习记录就好了:
// 代码部分
import java.util.Arrays;
public class CircleArrayQueue2 {
private int front;
private int tail;
private final int capacity;
private final int[] queue;
public CircleArrayQueue2(int capacity) {
this.capacity = capacity;
queue = new int[capacity];
}
// 判断环形队列是否为空
public boolean isEmpty() {
return front == tail;
}
// 判断环形队列是否已满
public boolean isFull() {
return (tail + 1) % capacity == front;
}
// 存
public void put(int n) {
if (isFull()) {
throw new IllegalArgumentException("queue is full !");
}
queue[tail] = n;
tail = (tail + 1) % capacity;
}
// 取
public int get() {
if (isEmpty()) {
throw new IllegalArgumentException("queue is empty !");
}
int n = queue[front];
queue[front] = 0;// 此处的目的是模仿讲引用置为null的操作
front = (front + 1) % capacity;
return n;
}
// 队首
public int catHead() {
if (isEmpty()) {
throw new IllegalArgumentException("queue is empty !");
}
return queue[front];
}
@Override
public String toString() {
return "CircleArrayQueue2{" +
"front=" + front +
", tail=" + tail +
", capacity=" + capacity +
", queue=[队首]" + Arrays.toString(queue) +
"[队尾], 队首元素: " + catHead() + "}";
}
}
// 测试类
public class CircleArrayQueueTest2 {
public static void main(String[] args) {
CircleArrayQueue2 circleArrayQueue2 = new CircleArrayQueue2(8);
for (int i = 1; i < 8; i++) {
circleArrayQueue2.put(i);
}
System.out.println(circleArrayQueue2);
circleArrayQueue2.get();
System.out.println(circleArrayQueue2);
circleArrayQueue2.get();
System.out.println(circleArrayQueue2);
circleArrayQueue2.put(8);
System.out.println(circleArrayQueue2);
circleArrayQueue2.put(9);
System.out.println(circleArrayQueue2);
circleArrayQueue2.put(10);
System.out.println(circleArrayQueue2);
}
}
// 测试结果
CircleArrayQueue2{front=0, tail=7, capacity=8, queue=[队首][1, 2, 3, 4, 5, 6, 7, 0][队尾], 队首元素: 1}
CircleArrayQueue2{front=1, tail=7, capacity=8, queue=[队首][0, 2, 3, 4, 5, 6, 7, 0][队尾], 队首元素: 2}
CircleArrayQueue2{front=2, tail=7, capacity=8, queue=[队首][0, 0, 3, 4, 5, 6, 7, 0][队尾], 队首元素: 3}
CircleArrayQueue2{front=2, tail=0, capacity=8, queue=[队首][0, 0, 3, 4, 5, 6, 7, 8][队尾], 队首元素: 3}
CircleArrayQueue2{front=2, tail=1, capacity=8, queue=[队首][9, 0, 3, 4, 5, 6, 7, 8][队尾], 队首元素: 3}
Exception in thread "main" java.lang.IllegalArgumentException: queue is full !
at com.sgu.data.structure.date_5_23.array.arrayqueue2.CircleArrayQueue2.put(CircleArrayQueue2.java:29)
at com.sgu.data.structure.date_5_23.array.arrayqueue2.CircleArrayQueueTest2.main(CircleArrayQueueTest2.java:18)
Process finished with exit code 1
// 分析
(tail + 1)% capacity :
我上面举的例子当中,测试结果第四个可以看到 tail 指向索引7(也就是最后一个元素)的位置,此时如果我再加一个元素tail应该指向0(环形队列嘛,索引7的下一个元素索引就是0),正好模运算就可以实现 (7 + 1)% 8 = 0,front 加 1之后和capacity取模是一个道理
capacity总是空出一个元素来判断队列是否已满:
仍然看我上面举的例子:当我添加完元素9以后,可以看到队列中索引为1的位置是空着的,当我再向队列中添加元素10时就开始报queue is full的错误了。原因是,如果加完元素10以后,tail的指针位置正好和front的指针位置重合(都在索引值为2的位置),我们说过了当front == tail时判断的是队列为空,所以为了和队列为空的条件区分开,就空出一个元素位置来作为队列已满的判断条件
下一篇: 分治算法实现汉诺塔