携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
本文的数组模拟环形队列是基于上文数组模拟队列之深度解析 - 掘金 (juejin.cn)、数组模拟队列(测试样例,含源码分析) - 掘金 (juejin.cn)所进行的代码深入剖析,读者可自行观看上文,再看本文效果最佳
1.4 数组模拟环形队列
1.4.1 分析说明
(1)尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意(rear + 1)% maxSize == front[满]
(2)rear == front[空]
(3)分析示意图
1.4.2 思路如下
(1)front
变量的含义做一个调整:front
就指向队列的第一个元素,也就是说arr[front]
就是队列的第一个元素,front的初始值 = 0
(2)rear
变量的含义做一个调整:rear
指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值=0
(3)当队列满时,条件是(rear + 1) % maxSize = front[满]
(4)当队列为空的条件,rear == front[空]
(5)队列中有效的数据的个数即为(rear + maxSize - front) % maxSize
1.4.3 代码实现
class CircleArray {
private int maxSize;
private int front;
private int rear;
private int[] arr;
复制代码
上方代码详解
(1)maxSize
即表示数组的最大容量
(2)front
即指向队列的第一个元素,也就是说arr[front]
是队列的第一个元素
(3)rear
即指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定
(4)int[] arr
用于存放数据,模拟队列
public CircleArray(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
}
复制代码
上方代码详解
(1)此处定义一个CircleArray
队列构造器,同时定义一个arrMaxSize
用于存储数组最大容量
(2)将arrMaxSize
赋值给ArrayQueue
的最大容量值maxSize
(3)开辟一个新的内存空间用于存放数组,并将其指针指向maxSize,即数组的最大容量,然后赋值给arr[]
用于存放数据,模拟队列
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
public boolean isEmpty() {
return rear == front;
}
复制代码
上方代码详解
(1)isFull()
:该方法用于判断队列是否满,当队列满时(见下图),故此时return (rear + 1) % maxSize == front
能够得到队列为满的判断
(2)isEmpty()
:该方法用于判断队列是否空,当队列空时,CircleArray
环形队列的头尾节点 “重合” ,表明此时队列里面没有数据,队列为空
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列满,不能添加数据");
return;
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
复制代码
上方代码详解
(1)我们定义一个void
类型的addQueue()
方法,并赋值参数n
用于添加数据
(2)如果环形队列已满,则System.out.println
告知读者队列已满,不能继续添加数据,并立即返回
(3)如果环形队列未满,则将参数n
赋值给数组arr
中rear
的位置,由于rear在环形队列中指rear
后一位,故无需考虑数组arr[0]
的问题
此时的rear
的位置将会由(rear + 1) % maxSize
所赋值过去,由于rear
本身自带+1属性,故在表达式中的 “ 1 ” 是给即将添加的数据准备的,而rear本身自带的+1是为腾出一个空间准备的
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,不能取出数据");
}
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
复制代码
上方代码详解
(1)我们定义一个getQueue()
方法用于获取队列中的数据
(2)首先得判断队列是否为空,故 if (isEmpty())
,如果为空,则抛出异常告知读者该队列为空,不能取出数据
(3)如果不为空,则定义一个变量value
作为用户取出的数值,同时将arr[front]
赋值给value,并将其作为取出的数值。由于front
自带 +1的属性,故无需考虑数组本身的特性
(4)front
后移一位留出一空,符合环形队列的约定,将其用于与数组最大容量maxSize
取模,得出此时环形队列front
应该在的位置,最终return value
public void showQueue() {
if (isEmpty()) {
System.out.println("队列空,没有数据");
return;
}
for (int i = 0; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
}
}
复制代码
上方代码详解
(1)我们定义一个showQueue()
方法用于展示队列的所有数据
(2)如果队列为空,则不能添加数据,同时通过 System.out.println()
告知读者队列为空并return
(3)通过for
循环遍历元素,size()
的作用已在上文说过,见数组模拟队列(测试样例,含源码分析) - 掘金 (juejin.cn)
(4)通过System.out.printf()
打印并格式化输出,arr[%d]
可以用i自增时候的数值去对该环形队列进行取模,得出该数组的实际位置,同时通过arr
数组锁定数值
public int size() {
return (rear + maxSize - front) % maxSize;
}
复制代码
上方代码详解
(1)我们定义一个size()
方法用于求出当前队列有效数据的个数
(2)当读者将rear
看作2,front
看作1,maxSize
看作3即可理解第二行代码的意思
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,没有数据");
}
return arr[front];
}
}
复制代码
上方代码详解
(1)我们定义一个headQueue()
方法用于显示环形队列的头数据
(2)如果为空,则抛出异常用于告知用户环形队列空,没有数据
(3)如果不为空 ,则返回数组中arr[]
中的front
的位置