方式均根据先进先出的思想,按照双指针的方式实现;
首先指针一 rear
代表了队列尾端,每新增一个数据则放置在队列尾部,同时rear的值增加1;
其次指针二 front
代表了队列的头部,每取出一个数据,则将队列头部的一个值拿出去,并使front的值加1;
然后是 maxSize
,它代表了数组的长度,限制队列所能承载的数据量。
1、用数组模拟队列
分析:
front 指向队列头的前一个位置
rear指向队列尾的数据的实际位置。它们的初始值都是 -1
队列满的条件: rear + 1 = maxSize
队列空的条件: rear == front
/**
* front和rear分别记录队列前后端的下标--双指针标记
* front随着数据输出而改变,rear随着数据输入而改变
*/
class ArrQueue implements MyQueue {
/** 表达数组的最大容量 */
private int maxSize;
/** 队列头 实际指向队列头的前一个位置*/
private int front;
/** 队列尾 实际指向队列尾的当前位置*/
private int rear;
/** 用于存放数据,模拟队列 */
private int[] arr;
public ArrQueue(int maxSize){
this.maxSize = maxSize;
arr = new int[maxSize];
front = -1;
rear = -1;
}
// 判断队列是否满
public boolean isFull(){
return rear == maxSize - 1;
}
// 判断队列是否为空
public boolean isEmpty(){
return rear == front;
}
// 添加数据到队列
public void addQueue(int n){
if (isFull()){
throw new RuntimeException("队列已满,不能加入数据");
}
arr[++rear] = n;
}
// 数据出列
public int pop(){
if (isEmpty()){
throw new RuntimeException("队列为空,没有可以获取的数据");
}
return arr[++front];
}
// 显示队列的所有数据
public void show(){
if (isEmpty()){
System.out.println("队列为空,没有数据展示");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n", i, arr[i]);
}
}
// 显示队列的头数据,不是显示
public int head(){
if (isEmpty()){
throw new RuntimeException("队列是空的喔");
}
return arr[front + 1];
}
}
2、数组实现环形队列
分析: front的值修改一下,front 指向队列头的数据的实际位置。
rear 指向队列尾的实际位置的后一个位置。并且rear和front的初始值为0
并且默认希望空出一个空间不能存放数据,是因为如果不空闲空间,那么队列满和队列为空的条件会发生冲突,因此队列满的条件应该如下:
队列满: (rear + 1) % maxSize == front
队列空: rear == front
队列中有效数据的个数是:( rear + maxSize - front ) % maxSize
代码如下
/**
* front和rear分别记录队列前后端的下标--双指针标记
* front随着数据输出而改变,rear随着数据输入而改变
* front和rear的后移需要考虑取模
*/
class CirCleQueue implements MyQueue{
/** 表达数组的最大容量 */
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()){
throw new RuntimeException("队列已满,不能加入数据");
}
arr[rear] = n;
// 此时rear需要后移,可能因为取模到前面来
rear++;
rear = rear % maxSize;
System.out.println("rear的值是:" + rear);
}
// 数据出列
public int pop(){
if (isEmpty()){
throw new RuntimeException("队列为空,没有可以获取的数据");
}
int i = arr[front];
// 修改 front的值
front++;
front = front % maxSize;
System.out.println("front 的值是:" + front);
return i;
}
// 因为可以循环使用,因此显示队列的所有数据是从front开始,遍历剩下的所有元素
public void show(){
if (isEmpty()){
System.out.println("队列为空,没有数据展示");
return;
}
// 遍历有效数据的个数那么多个,如下面的方法
for (int i = front; i < (front + effective()); i++) {
int num = i % maxSize;
System.out.printf("arr[%d] = %d\n", num, arr[num]);
}
}
// 求出有效数据的个数
public int effective(){
return (rear + maxSize - front) % maxSize;
}
// 显示队列的头数据,不是显示
public int head(){
if (isEmpty()){
throw new RuntimeException("队列是空的喔");
}
return arr[front];
}
}
网友评论