理论补充
在笔者 2.1 队列 文章中只是讲解基本队列的实现,该方式在队列中空间使用后就不能再被使用空间浪费大。为了优化程序,队列中使用过的空间需要复用因此使用循环队列实现队列空间最大化使用。(注:本文也是基于数组实现循环链表)
## 1.前置参数说明:
参数 | 说明 |
---|---|
front | 队头,初始值0 |
rear | 队尾,初始值为0 |
maxSize | 队列大小 |
(rear+maxSize-front)%maxSize | 有效数据个数 |
(rear+1)/maxSize == front | 队满 |
代码实现
package com.b0.a1_2queue;
import java.util.Scanner;
public class CircleArrayQueueDemo {
public static void main(String[] args) {
System.out.println("=====测试环形队列=====");
//创建一个队列
CircleArrayQueue queue = new CircleArrayQueue(4);
//接受用户输入的指令
char key=' ';
Scanner scanner = 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 = scanner.next().charAt(0);//接收一个字符
switch (key){
case 's':
queue.showQueue();
break;
case 'a':
System.out.print("请输入一个数:");
int i = new Scanner(System.in).nextInt();
queue.addQueue(i);
break;
case 'g':
try{
System.out.println("取出值为:"+queue.getQueue());
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h':
try{
System.out.println("队头值为:"+queue.headQueue());
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序结束");
}
}
class CircleArrayQueue{
private int maxSize;//表示队列的最大容量
private int front;//队列头
private int rear;//队列尾
private int[] arr;//存放数据的队列
public CircleArrayQueue(int arrMaxSize){
maxSize = arrMaxSize;
arr = new int[maxSize];
//头尾变量默认初始化为0可以不写
// 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;
}
//直接将数据加入,因为rear指向的是队列最后一个元素的后一个位置
arr[rear] = n;
//将rear后移,这里必须考虑取模
rear = (rear+1)%maxSize;
}
//取出队列的值,出队
public int getQueue(){
//判断是否队空
if (isEmpty()){
throw new RuntimeException("队列为空不能取出数据!");
}
//这里需要分析出front是指向队列的第一个元素
//1.先把front对应的值保存到一个临时变量
//2.将front后移(不是直接++),考虑取模
//3.将临时变量返回
int value = arr[front];
front = (front + 1)%maxSize;
return value;
}
//显示队列所有数据
public void showQueue(){
//队列为空
if (isEmpty()){
System.out.println("队列为空!");
return;
}
//从front开始遍历,遍历多少个元素
System.out.println("队列数据为:");
for (int i=front;i<front+size();i++) {
System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
}
System.out.println();
}
//求出当前队列有效数据的个数
public int size(){
return (rear+maxSize-front)%maxSize;
}
//显示头数据,不取出
public int headQueue(){
//判断
if (isEmpty()){
throw new RuntimeException("队列为空,没有数据");
}
return arr[front];
}
}