完整代码如下:
package com.wqc.queue;
import java.util.Arrays;
import java.util.Scanner;
/**
* @author 高瞻远瞩
* @version 1.0
* @motto 算法并不可怕, 可怕的是你不敢面对它, 加油!冲击大厂!!!
*改进:循环队列
* 经修改过后 rear的初始值为0 front的初始值也为0
* 当rear=0 时 先入队第一个元素 然后rear再加1
* 当(rear+1)%maxSize = front 时 说明队列满
*
* 经修改过后 队列为null的条件变为 front == rear
*/
@SuppressWarnings({"all"})
public class CircleArrayQueueDemo {
private int maxSize;//定义队列的最大容量
private int rear;// 指定队尾的元素的下一个位置 预留一个空间 初始值也为0
private int front;// 初始指向队头元素 初始值为0
private int[] arr;//定义一个数组
public CircleArrayQueueDemo(int size) {
maxSize = size;
arr = new int[maxSize];
}
public static void main(String[] args) {
CircleArrayQueueDemo arrayQueue = new CircleArrayQueueDemo(3);
boolean loop = true;
while (loop) {
System.out.println("1,判断队列是否为满");
System.out.println("2,判断队列是否为空");
System.out.println("3,向队列中添加元素");
System.out.println("4,向队列取出元素");
System.out.println("5,显示所有数据");
System.out.println("6,查看队头元素");
System.out.println("7,退出");
System.out.print("请输入你的选择:");
Scanner scanner = new Scanner(System.in);
String key = scanner.next();
switch (key) {
case "1":
if (arrayQueue.isFull()) {
System.out.println("\n队列已满\n");
} else {
System.out.println("\n队列未满\n");
}
break;
case "2":
if (arrayQueue.isEmpty()) {
System.out.println("\n队列为空\n");
} else {
System.out.println("\n队列不为空\n");
}
break;
case "3":
System.out.print("请输入你要添加的元素:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case "4":
int queue = 0;
try {
queue = arrayQueue.getQueue();
System.out.println("\n取出的元素为:" + queue);
} catch (Exception e) {
System.out.println(e.getMessage());//捕获到异常 输出异常信息
}
break;
case "5":
arrayQueue.showAll();
break;
case "6":
int head = 0;
try {
head = arrayQueue.getHead();
System.out.println("\n队头元素为:" + head);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "7":
System.out.println("你退出了程序");
loop = false;
break;
default:
System.out.println("你输入的有误,请重试");
}
}
}
//判断队列是否为满
public boolean isFull() {
return (rear+1)%maxSize == front;
// 分析上面的一句话 rear+1(含义是队尾元素的下一个位置)的最大值为maxSize
// 然后和 maxSize取模的话为0 此时刚好时front指向的数组下标0位于的第一个元素
// 修改过后的front的定义为指定数组下标的第一个元素 即初始值为0 所以这样的理解是对的
}
//判断队列是否为空
public boolean isEmpty() {
return front == rear;
}
//向队列中添加元素
public void addQueue(int n) {
//添加之前需要判断队列是否为满
if (isFull()) {
System.out.println("队列已满,添加失败...");
return;
}
arr[rear] = n;
// rear++;//rear++的话会越界 所以要进行取模
/*
假设maxSize = 3;
rear初始值为0 先加入到数组0号位置 加入成功 然后+1进行取模=1 rear = 1
然后第二次加入 这时候rear = 1 所以加入到数组1号索引的位置 加入成功 然后再加1 进行取模 = 2 rear = 2
然后进行第三次加入 这时候rear = 2 判断为满的条件变成了(2+1)%3 = 0 == front
所以加入失败 预留了一个索引为2的位置
当所有元素都取出时 front变为2 此时不符合为满的条件
所以可以进行第三次加入 第三次加入时 先加入到索引为2的位置 然后(rear+1)%3=0 rear=0
第四次加入就加到0号索引位置 这时候rear=1
当再进行第5次加入 (rear+1)%3=2 这时候等于front 所以符合队列为满的条件
*/
rear = (rear+1)%maxSize;
System.out.println("添加成功...");
}
//向队列取出元素
public int getQueue() {
//取之前需要判断队列是否为null
if (isEmpty()) {
throw new RuntimeException("\nQueue is empty");
}
//如果直接return 了 front就不能再加了 所以先把要返回的数保存到一个临时变量里面
int temp = arr[front];
// front++;//这里也要进行取模
front = (front+1)%maxSize;
/*
分析这个取模运算
假设maxSize=3 当队列满时
向队列中取第一个元素 此时front=0 front+1取模后=1 取出成功 front变为1
取第二个元素时 此时front=1 再加1取模后=2 这时候也取出成功 front变成2
取第三个元素时 因为front=rear 都等于2 符合为空的条件 所以这时候不能取出 只能加入元素
*/
return temp;
}
//显示队中所有的数据
public void showAll() {
for (int i = front; i < front+showNums(); i++) {
System.out.printf("arr[%d] = %d\n", i%maxSize, arr[i%maxSize]);//因为再不停的向队列中添加
}
//分析一下这个for循环
//初始的时候加入两个元素 i=front=0 i<2 i++ 循环两次 输出arr[0] arr[1]
//然后取出两个元素后 front变为2 再添加两个元素 i=2 i<2+2=4 i++ 循环两次 输出arr[2] arr[0]
//所以在显示数据时 i也要取模
}
//显示队中的有效数据
public int showNums(){
return (rear-front+maxSize)%maxSize;
}
//查看队头元素
public int getHead() {
if (isEmpty()) {
throw new RuntimeException("Queue is empty");
}
return arr[front];
}
}