基本数组模拟队列
- 定义队列头和队列尾(rear 是队列最后[含] front 是队列最前元素[不含])
- 定义队列的最大长度
//数组模拟队列--ArrayQueue类
class ArrayQueue1{
private int maxSize; //队列长度
private int front; // 队列头
private int rear; // 队列尾
private int[] arr; // 模拟队列的数组
//初始化队列,将最大长度给数组初始化
public ArrayQueue1(int arrMaxSize){
maxSize = arrMaxSize; // 队列最大长度
arr = new int[maxSize];
front = -1; // 指向队列头部,指向队列头的前一个位置
rear = -1; // 指向队列的队列尾,指向最后一个数据(就是队列最后一个数据)
}
// 判断队列已满,当队列尾指向数组的头时代表队列已满
public boolean isFull(){
return rear == maxSize -1;
}
// 判断队列是否为空,队列的头和尾指向统一个地方时,代表队列为空
public boolean isEmpty(){
return rear == front;
}
/**
在队列中添加数据时
1. 将尾指针往后移:rear+1 , 当front == rear 【空】
2. 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1[队列满]
*/
//在队列中添加数据
public void addQueue(int num){
if(isFull()){
System.out.println("队列已满,不能添加数据");
return;
}
rear++; // 队尾后移
arr[rear] = num;
}
/**
1. 判断队列是否为空,为空则抛出异常 (rear== front则队列为空)
2. front指向队首的前一个位置,front后移指向队首元素
*/
// 获取队列数据
public int getQueue(){
if(isEmpty()){
throw new RuntimeException("队列为空,无数据"); // 抛出异常后的下面代码不会执行
}
front++; //队首后移
return arr[front];
}
//显示队列的所有数据
public void showQueue(){
//遍历
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 headQueue(){
//判断
if(isEmpty()){
System.out.println("队列为空,没有数据");
throw new RuntimeException("队列为空,没有数据");
}
return arr[front+1];
}
}
存在问题: 只能实现单次使用,无法服用
优化方向: 将数组改为环形
环形数组模拟队列
-
front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素 front 的初始值 = 0
-
rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定. rear 的初始值 = 0
-
当队列满时,条件是 (rear + 1) % maxSize == front 【满】
-
对队列为空的条件, rear == front 空
-
当我们这样分析, 队列中有效的数据的个数 (rear + maxSize - front) % maxSize // rear = 1 front = 0
-
我们就可以在原来的队列上修改得到,一个环形队列
代码如下:
class CricleQueue{
private int maxSize; //队列的最大容量
private int front; //队列头 指向队列的第一个元素
private int rear; //队列尾 指向队列最后一个元素的后一个位置
private int[] arr; //存放队列数据的数组
// 创建队列的构造器
public CricleQueue(int arraySize) {
maxSize = arraySize;
arr = new int[arraySize];
front = 0; //指向队列头的数据
rear = 0; // 指向队列尾数据的 后一个位置
}
// 判断队列是否已满
public boolean isFull() {
// 数组从0开始,最后
return (rear + 1) % maxSize == front ;
}
// 判断队列是否为空
public boolean isEmpty() {
return front == rear;
}
// 队列中添加数据
public void addQueue(int num) {
// 判断队列是否已满
if(isFull()) {
System.out.println("队列已满,不能添加");
return;
}
arr[rear] = num;
// rear必须取模,否则rear超出数组的最大长度
rear = (rear +1) % maxSize;
}
// 队列中提取数据
public int getQueue() {
if(isEmpty()) {
throw new RuntimeException("队列中没有数据!");
}
/* front指向队列的第一个元素
1. 将front位置的值赋给一个临时变量
2. front后移
3. 返回临时变量
*/
int value = arr[front];
// 与rear同理
front = (front+1) % maxSize;
return value;
}
// 求出当前队列有效数据的格式
public int size() {
return (rear + maxSize - front) % maxSize ;
}
//查看整个队列
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 headQueue() {
//判断
if(isEmpty()){
System.out.println("队列为空,没有数据");
throw new RuntimeException("队列为空,没有数据");
}
return arr[front];
}
}