packagecom.zzfan.queue;import java.util.*;public classCircleArrayQueue {public static voidmain(String[] args) {
System.out.println("测试数组环形队列");//创建一个环形队列
CircleArray queue = new CircleArray(4); //队列有效数据最大是3
char key = ' '; //接收用户输入
Scanner scanner = newScanner(System.in);boolean loop = true;//输出菜单
while(loop) {
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");//接收一个字符
key = scanner.next().charAt(0);switch(key) {case 's':
queue.showQueue();break;case 'a':
System.out.println("输出一个数");int value =scanner.nextInt();
queue.addQueue(value);break;case 'g':try{int result =queue.getQueue();
System.out.printf("取出的数据是%d\n", result);
}catch(Exception e) {
System.out.println(e.getMessage());
}break;case 'h':try{int result =queue.headQueue();
System.out.printf("头部的数据是%d\n", result);
}catch(Exception e) {
System.out.println(e.getMessage());
}break;case 'e':
scanner.close();
loop= false;break;default:break;
}
}
System.out.println("程序退出");
}
}classCircleArray {//数组的最大容量
private intmaxSize;//front指向队列的第一个元素,也就是说arr[front]是队列的第一个元素
private intfront;//rear指向队列的最后一个元素的最后一个位置,初值为0
private intrear;private int[] arr; //该数据用于存放数据,模拟队列
public CircleArray(intarrMaxSize) {
maxSize=arrMaxSize;
arr= new int[maxSize];
}//判断是否满
public booleanisFull() {return (rear + 1) % maxSize ==front;
}//判断是否为空
public booleanisEmpty() {return rear ==front;
}//添加数据到队列
public void addQueue(intn) {//判断队列是否已满
if(isFull()) {
System.out.println("队列已满");return;
}//直接将数据加入
arr[rear] =n;//将rear后移,必须考虑取模
rear = (rear + 1) %maxSize;/*这里手算了一下,实际取模就是想办法当rear和队列最大容量相等时,在加1就重新取到rear=1
有个通俗易懂的例子:跑步套圈
有一个环形跑道,假设,将环形跑道分割成10份。
front某时刻跑到第3格了,rear此时刻已经跑到第10格了。
那么rear继续往下跑的时候,会发现,跑的第“11格”(实际并不存在)其实就是第1格,是第二圈的第1格。*/}//获取队列的中的数据
public intgetQueue() {//判断队列是否空
if(isEmpty()) {//通过抛出异常来处理
throw new RuntimeException("队列为空,无法取出数据");//throw可以直接return一个异常,不用再写return
}//front指向队列的第一个元素
/*1. 先把front对应的值保留到一个临时变量中
2. front后移,考虑取模
3. 将临时保存的变量返回*/
int value = arr[front]; //先获取数据,front再后移
front = (front + 1) %maxSize;returnvalue;
}//显示队列的所有数据
public voidshowQueue() {//遍历数组
if(isEmpty()) {
System.out.println("队列为空,没有数据");return;
}//从front开始遍历,对需要遍历元素的个数进行计算。
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d] = %d\n", i % maxSize, arr[i %maxSize]);
}
}//有效数据的个数
public intsize() {return (rear + maxSize - front) %maxSize;/*添加数据变的是rear,取出数据变的是front,所以当在第一个位置插入数据时,rear=2,front=1。
所以,如果不考虑取模,那有效数据个数就是rear-front
考虑取模的话会出现一种情况,rear已经开始“跑第二圈”了,front还在“第一圈”*/}//显示队列头
public intheadQueue() {//判断是否为空
if(isEmpty()) {throw new RuntimeException("队列为空,没有数据");
}returnarr[front];
}
}