数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组. 因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:
- 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front
假设maxsize=4 那实际只能放3个值 arr[0], arr[1], arr[2],当添加到 arr[rear] arr[2] (rear+1)%4 =3 在添加下一次值的时候 (3+1)%4=0=front 此时队列满了,存了3个数。
当有一个数出队列,(front+1)%4=1 front变为1.
此时添加数据 ,判断满 rear还是等于 (3+1)%4不等于front arr[3] 下一位又是0
rear
2) rear == front [空]
3) 分析示意图
代码实现
import java.util.Scanner;
public class CircleDemo {
public static void main(String[] args) {
CircleQueue queue=new CircleQueue(3); //中间有预留空位,实际容量为2
char key=' '; //接受的用户指令
Scanner sc=new Scanner(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 = sc.next().charAt(0);//接收一个字符
switch (key) {
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("输出一个数");
int value = sc.nextInt();
queue.addQueue(value);
break;
case 'g': //取出数据
try {
int res = queue.getQueue();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h': //查看队列头的数据
try {
int res = queue.peek();
System.out.printf("队列头的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e': //退出
sc.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出~~");
}
}
class CircleQueue{
private int maxSize; //数组的最大容量
private int front; //队头
private int rear; //队尾
private int[] arr; //存放数据的数组,模拟队列
//创建队列的构造方法 给定队列大小
public CircleQueue(int maxSize){
this.maxSize=maxSize;
arr=new int[maxSize];
front=0;
rear=0;
}
//判断队列是否已满
public boolean isFull(){
return (rear+1)%maxSize==front;
}
//判断队列是否为空
public boolean isEmpty(){
return rear==front; //头尾指到一个位置 说明没有数据
}
//添加数据到队列
public void addQueue(int n){
//先判断队列是否已满
if(isFull()){
System.out.println("队列已满,不能加入");
return;
}
arr[rear]=n;
rear=(rear+1)%maxSize; //是环 跳到最前面空的
}
//出队列
public int getQueue(){
//先判断队列是否为空
if(isEmpty()){
throw new RuntimeException("队列为空");//抛出运行时异常 队列为空
}
int value=arr[front];
front=(front+1)%maxSize; //环形要取模
return value;
}
//显示队列所有数据
public void showQueue(){
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 int size(){
return (rear-front+maxSize)%maxSize;
}
//显示队列头 ,注意不是取出头
public int peek(){
if(isEmpty()){
throw new RuntimeException("对列为空");
}
return arr[front];
}
}
测试
注意看每次的队列的索引
队列是有个空位 ,让队列可以一直循环
0,1,2
取掉第一个
1,2,3
取掉前两个
3 ,0,1
"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:D:\idea\IntelliJ IDEA 2022.1\lib\idea_rt.jar=50042:D:\idea\IntelliJ IDEA 2022.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_221\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar;D:\idea-workspace\20220508\out\production\20220508" CircleDemo
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
1
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
2
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
s
arr[0]=1
arr[1]=2
arr[2]=3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
g
取出的数据是1
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
4
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
s
arr[1]=2
arr[2]=3
arr[3]=4
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
g
取出的数据是2
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
g
取出的数据是3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
5
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
6
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
s
arr[3]=4
arr[0]=5
arr[1]=6
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据