利用数组实现的环形队列,主要方法和思考过程都在代码里面。
package algorithm.structure;
/**
* @Author: M˚Haonan
* @Date: 2021/1/9 18:08
* @Description: 数组实现的环形队列
* 这种环形队列,队列的容量是要比数组长度少1的,因为只有留下一个空余空间,才能判断出来是满还是空
* 如果全占,满和空的时候两个指针都是重叠的,没法判断
*/
public class ArrayQueue {
//头指针,指向第一个元素
private int head;
//尾指针,指向最后一个元素之后的位置,这个非常重要
private int tail;
//存放元素
private int[] arr;
//队列的容量
private int capacity;
//数组的长度,比容量大1
private int arrLen;
public ArrayQueue(int capacity) {
this.capacity = capacity;
arr = new int[this.capacity + 1];
arrLen = arr.length;
head = 0;
tail = 0;
}
//第一种满 如果tail > head 那么 tail + 1 - head == arrLen
//第二种满 如果tail < head 那么 tail + 1 - head == 0
//那么合二为一就是 (tail + 1 - head) % arrLen == 0;
public boolean isFull() {
return (tail + 1 - head) % arrLen == 0;
}
//当两个指针重叠的时候,队列为空
public boolean isEmpty() {
return head == tail;
}
public void add(int num) {
if (isFull()) {
System.out.println("队列已满,无法加入");
return;
}
arr[tail] = num;
//取余也就相当于这样 tail = tail == arrLen - 1 ? 0 : tail + 1;
//取余的妙用,比如a % b,那么结果就是0 ~ (b - 1)循环
tail = (tail + 1) % arrLen;
}
public int pop() {
if (isEmpty()) {
System.out.println("队列为空");
throw new RuntimeException("队列为空");
}
int ele = arr[head];
// head = head == arrLen - 1 ? 0 : head + 1;
head = (head + 1) % arrLen;
return ele;
}
public void print() {
int currHead = head;
int currTail = tail;
while (currHead != currTail) {
System.out.println(arr[currHead]);
//currHead = currHead == arrLen - 1 ? 0 : currHead + 1;
currHead = (currHead + 1) % arrLen;
}
}
//如果tail >= head valid = tail - head
//如果tail < head valid = arrLen - (head - tail)
// arrLen + tail - head
//如果合二为一,那么就是 valid = (arrLen + tail - head) % arrLen
//取余可以保证不超过arrLen,当tail >= head时,取余可以把 + arrLen抵消掉,相当于 + 0
//当tail < head 时,取余相当于没取余,结果是arrLen + tail - head
public int getValidNum() {
return (arrLen + tail - head) % arrLen;
}
public static void main(String[] args) {
ArrayQueue queue = new ArrayQueue(3);
queue.add(1);
queue.pop();
queue.add(2);
queue.add(4);
queue.pop();
queue.add(5);
queue.add(5);
queue.add(5);
System.out.println("队列有效个数为" + queue.getValidNum());
queue.print();
}
}