数组模拟队列的优化——数组模拟环形队列
【摘要】 数组模拟环形队列
数组模拟环形队列
程序优化思路
(1)front 变量的含义进行一个调整:让 front 指向队列的第一个元素,也就是说 arr[front] 为队列的第一个元素,front 的初始值为0。
(2)rear 变量的含义做一个调整:让 rear 指向队列的最后一个元素的后一个位置,因为要空出一个空间来做约定,rear 的初始值为0.
(3)当队列为满时,条件为(rear + 1) % maxSize == front
例如当 rear = 2 ,front = 0 时,maxSize - 1 = 2,maxSize = 3(因为下标从零开始),所以(2 + 1) % 3 == 0,所以队列已满。
(4)当队列为空时,条件为 rear == front
(5)分析完成后,该队列中有效数据的个数是 (rear + maxSize - front) % maxSize
例如当 rear = 2,front =0,maxSize = 3时,(2 + 3 - 0) % 3 等于 2 ,说明该队列中有效数据的个数为两个。
(6)修改之前的队列,得到一个新的环形队列
使用数组模拟环形队列—编写一个CircleArrayQueue类
class CircleArrayQueue {
private int maxSize;//队列的长度,也就是最多能存储多少个数据
private int front;//队列头
private int rear;//队列尾
private int[] arr;//用于存放数据,模拟队列
//创建队列的构造器
public CircleArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
/*
front 变量的含义进行一个调整:让 front 指向队列的第一个元素,
也就是说 arr[front] 为队列的第一个元素,front 的初始值为0。
rear 变量的含义做一个调整:让 rear 指向队列的最后一个元素的后一个位置,
因为要空出一个空间来做约定,rear 的初始值为0.
*/
//因为front 和 rear 默认为零,所以不用进行赋值
}
//判断队列是否满
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很有可能会产生越界
rear = (rear + 1) % maxSize;
}
//获取队列的数据,出队列
public int getQueue() {
//判断队列是否为空
if(isEmpty()) {
//如果为空就抛出异常
throw new RuntimeException("队列为空,不可以读取数据");
//return //不需要进行返回,因为抛出异常就已经等于进行了返回
}
/*
这里需要分析出 front 是指向队列的第一个元素
1.先把 front 对应的值保存到一个临时变量中
(如果不把值保存到临时变量中,那么 front 就没有往后移的机会了)
2.将 front 后移,并且考虑取模,因为front也有可能会产生越界
3.将临时保存的变量返回
*/
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 + number(); i++) {
System.out.print(arr[i % maxSize] + " ");
//因为 i 在运行时可能会超过数组的大小,所以要进行模除
}
}
//求出当前队列有效数据的个数
public int number() {
return (rear + maxSize - front) % maxSize;
}
//显示队列的头数据,注意不是读取数据
public int headQueue() {
//判断是否为空
if(isEmpty()) {
throw new RuntimeException("队列为空,无法输出");
}
return arr[front];
//front 不需要 +1 是因为 front 本身就指向队列的第一个元素
}
}
编写CircleArrayQueueDemo类进行调用方法演示
import java.util.Scanner;
public class CircleArrayQueueDemo {
public static void main(String[] args) {
//创建环形队列进行测试
CircleArrayQueue circleArrayQueue = new CircleArrayQueue(5);
//因为要空出一个空间来做约定,所以队列长度为5,但最多只能存入4个元素
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while(loop) {
System.out.println("s(show):显示队列");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
System.out.println("e(exit):退出程序");
System.out.println("=====请输入要求=====");
char key = scanner.next().charAt(0);//接收用户输入的一个字符
switch(key) {
case 's'://显示队列
circleArrayQueue.showQueue();
System.out.println();
break;
case 'a'://添加数据到队列
System.out.println("请输入一个整数:");
int value = scanner.nextInt();
circleArrayQueue.addQueue(value);
break;
case 'g'://取出数据
//取出数据时可能会遇到异常,因为有可能没有数据可以取出
//所以要使用异常处理机制try catch
try {
int res = circleArrayQueue.getQueue();
//如果getQueue()没有抛出异常,就会取出数据
System.out.println("取出的数据是:" + res);
} catch (Exception e) {
//如果getQueue()抛出异常,就会被catch抓住
//所以会在catch中输出异常信息
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'h'://查看队列头的数据
try {
int res = circleArrayQueue.headQueue();
System.out.println("队列头的数据是:" + res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'e'://退出程序
scanner.close();//退出前先把scanner关闭,如不关闭可能会有异常
loop = false;//如果退出程序那么loop就为false,while循环就不会通过
break;
default:
break;
}
}
System.out.println("程序已退出");
}
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)