数组模拟循环队列(Java代码)
用数组来模拟循环队列
在循环队列中,保留一个单元。即队列中还有一个位置的时候,就默认认为队列已满
判断队列已满的条件
private int maxSize;// 队列容量,队列可存放数据的大小是队列容量-1
private int front;// 队列头,起始为0,表示队列第一个有值的元素的位置
private int rear;// 队列尾,起始为0,表示队列最后一个有值的元素的下一个位置
private int[] arr;// 存放数据模拟队列
重点理解如何判断队列满和求出当前队列有多少个元素(rear + 1) % maxSize == front可以理解成,队尾已经绕了一圈赶到了队列头的位置,则队列已满(注意保留一个空闲的位置)
建议忽略 %maxSize 来理解 即rear的下一个位置是front时,循环队列已满
取模的原因是保证队列的头和尾在这个数组的范围内
判断队列有多少个元素
(rear + maxSize - front) % maxSize先不取模来理解,同样用上图,队列有多少个元素可以简单理解成rear-front,考虑到rear可能在front的前面,于是加上maxSize 再对整个值取模来表示当前队列有多少个元素
掌握这两个难点后即可模拟队列
完整代码如下
package com.queue;
import java.util.Scanner;
//模拟环形队列
public class CircleQueueDemo {
public static void main(String[] args) {
// 模拟队列的实现
CircleQueue aq = new CircleQueue(4);
Scanner sc = new Scanner(System.in);
int input;
boolean flag = true;
while (flag) {
System.out.println("请输入操作,1 查看整个队列 2 增加元素 3 元素出队列 4 查看头部");
input = sc.nextInt();
switch (input) {
case 1:
aq.showQueue();
break;
case 2:
System.out.println("请输入要增加的数字");
int in = sc.nextInt();
aq.add(in);
break;
case 3:
try {
int queue = aq.getQueue();
System.out.println(queue + "出队列了");
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 4:
try {
int showHead = aq.showHead();
System.out.println("头部是" + showHead);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
break;
}
}
sc.close();
}
}
class CircleQueue {
private int maxSize;// 队列容量
private int front;// 队列头,起始为0,表示队列第一个有值的元素的位置
private int rear;// 队列尾,起始为0,表示队列最后一个有值的元素的下一个位置
private int[] arr;// 存放数据模拟队列
public int getRear() {
return rear;
}
public void setRear(int rear) {
this.rear = rear;
}
public CircleQueue(int maxSize) {
this.maxSize = maxSize;// 传入的容量设置为队列容量,但预留最后一个空间为空
front = 0;// 指向队列头部的位置
rear = 0;// 指向队列尾部的下一个位置,并且空出最后一个空间
arr = new int[maxSize];// 设置存放数据的数组的大小
}
// 判断队列是否满
public boolean isFull() {
return (rear + 1) % maxSize == front;// 可带数字验算得出,比如容量为4,只能装3个元素。当front是0,rear是3时则满了,因为arr[0]和arr[1],arr[2]都装了
// 再比如,front是1,有3个元素arr[1],arr[2],arr[0],此时rear是0(下标3的下一个就变回0)
}
// 判断队列是否为空
public boolean isEmpty() {
return front == rear;// 头和尾指向同一个位置证明是空
}
// 添加数据到队列
public void add(int n) {
// 如果满了则不能添加
if (isFull()) {
System.out.println("满了,不能加数据");
return;
}
arr[rear] = n;// 把数据放入最后一个有元素的位置的下一个(即rear)
rear = (rear + 1) % maxSize;// 后移,但要考虑取模问题
}
// 数据出队列
public int getQueue() {
// 如果为空,则抛出异常
if (isEmpty()) {
throw new RuntimeException("队列为空,没有数据可以出队列");
}
int val = arr[front];
arr[front] = 0;
front = (front + 1) % maxSize;// 取完数据后,让头部向下一个位置移动,考虑取模的问题
return val;
}
// 显示队列的所有数据
public void showQueue() {
// 如果为空
if (isEmpty()) {
System.out.println("队列空,没数据显示");
return;
}
// 从front开始,遍历有多少个值
for(int i = front;i<=front + showValuesCount();i++) {
System.out.println("arr ["+ i%maxSize + "]的值是 "+arr[i%maxSize]);
}
}
// 求出当前队列有多少个值
public int showValuesCount() {
return (rear + maxSize - front) % maxSize;//假如maxsize是4,front是1,rear是3,即当前arr[1]和arr[2]是有值的,值的个数为2
}
// 显示头数据,不是取数据
public int showHead() {
// 如果为空
if (isEmpty()) {
throw new RuntimeException("队列为空,没有头数据");
}
return arr[front];
}
}
