基于数组的循环队列
基于数组的循环队列关键点在于:当元素总数达到队列的阈值后,出队、入队等行为如何避免数组越界问题
。
循环数组的逻辑结构可以类比时钟,当指针走到最后一个刻度(比如12小时制的12点),再往前走时,指针会回到最开始的刻度(即1点),而不是继续前进到一个不存在的位置。
以 12 小时制 时钟为例,时钟的循环特性可以通过 线性取余 来类比,取余操作有效地实现了“溢出之后重新开始”的效果。下面是如何通过线性取余来类比时钟循环下一个 12 小时的步骤。
时钟与线性取余的类比:
- 时钟的循环特性:
- 12 小时制时钟从 1 点到 12 点循环。当到达 12 点后,再前进一个小时,它会回到 1 点,而不是 13 点。
- 对于任何时刻,时钟上的下一个时间点可以通过
当前时间 + 1
来计算,但如果超过 12 点,需要回绕到 1 点。
- 取余的数学表示:
- 如果当前时间是
h
,我们可以使用(h + 1) % 12
来计算下一个小时。取余操作保证了时间在 1 到 12 之间循环。
- 如果当前时间是
由此可知,循环数组的head指针
和tail指针
,都可以通过取余的方式实现循环步进。
查看代码
public class Main {
public static void main(String[] args) {
System.out.println("pop 出队");
System.out.println("push 入队");
System.out.println("show 展示队列数据");
System.out.println("exit 结束程序");
CycleQueue queue = new CycleQueue(5);
Scanner outer = new Scanner(System.in);
Scanner inner = new Scanner(System.in);
System.out.println("------------------ read? go! ------------------");
while (true) {
String command = outer.nextLine();
if ("pop".equals(command)) {
try {
int value = queue.pop();
System.out.println(value);
} catch (Exception e) {
System.out.println(e.getMessage());
}
} else if ("push".equals(command)) {
int value = inner.nextInt();
queue.push(value);
} else if ("show".equals(command)) {
queue.show();
} else if ("exit".equals(command)) {
break;
} else {
System.out.println("不支持的操作");
}
}
System.out.println("------------------over------------------");
}
static class CycleQueue {
// 头指针
private int head;
// 尾指针
private int tail;
private int size;
private int[] arr;
public CycleQueue(int i) {
size = i;
arr = new int[size];
}
public boolean isFull() {
return (tail + 1) % size == head;
}
public boolean isEmpty() {
return head == tail;
}
/**
* 出队
*/
public int pop() {
if (isEmpty()) {
throw new RuntimeException("队列为空~");
}
int res = arr[head];
head = (head + 1) % size;
return res;
}
/**
* 入队
*/
public void push(int i) {
if (isFull()) {
System.out.println("队列已满~");
return;
}
arr[tail] = i;
tail = (tail + 1) % size;
}
public void show() {
if (isEmpty()) {
System.out.println("队列为空,无数据~");
return;
}
// System.out.println("队列中的数据为:");
// 计算队列中的元素数量
int count = (tail - head + size) % size;
// 通过循环展示所有数据
for (int i = 0; i < count; i++) {
int index = (head + i) % size;
System.out.printf("arr[%d] = %d\n", index, arr[index]);
}
}
}
}