什么是队列:队列是一个有序列表。可以使用数组或列表实现。
遵循:先进先出的原则。队尾入队,队头出队。
队列容量 maxSize:队列中存放数据元素的最大个数
队列前端 front:队头,在第一个数据元素之前
队列后端 rear:队尾,指向最后一个数据元素
队列操作:
入队:rear+1后,再入队
出队:front+1后,再出队
判断队满:rear+1==maxSize,根据队尾来判断
判断队空:rear == front,根据队头和队尾来判断
打印队列数据:
获取队头数据:
创建一个队列类(注意:新建的这个ArrayQueue类是在ArrayQueueDemo这个类的外面)
可以通过抛出异常来输出提示信息,抛出异常后会自动结束这段代码运行(相当于return)
获取数据(出队)、显示数据
获取队头数据
测试代码(建立一个菜单)
使用数组存储队列数据存在的问题:数组不能重复使用(只能使用一次)
完整代码:
package com.Queue_02;
import java.util.Scanner;
public class ArrayQueueDemo {
/**
* 1. 创建一个ArrayQueue类,用数组来模拟队列
* 2. 添加属性
* 3. 添加构造方法,初始化属性
* 4. 判断队空
* 5. 判断队满
* 6. 添加数据(入队)
* 7. 获取数据(出队)
* 8. 显示队列数据
* 9. 显示队头数据
* 10. 测试(添加菜单,测试相关队列操作)
*/
public static void main(String[] args) {
// 10. 测试(添加菜单,测试相关队列操作)
ArrayQueue arrayQueue = new ArrayQueue(3);
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':
arrayQueue.showQueue();
break;
case 'a':
System.out.print("请输入一个数:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int res = arrayQueue.getQueue();
System.out.printf("取出的数据是:%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());;
}
break;
case 'h':
try {
int res = arrayQueue.headQueue();
System.out.printf("队头数据是:%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());;
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出~~~");
}
}
// 使用数组模拟队列——编写一个ArrayQueue类
class ArrayQueue{
private int maxSize; // 队列的最大容量
private int front; // 队头
private int rear; // 队尾
private int[] arr; // 存放队列数据,模拟队列
// 创建队列的构造器
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1;
rear = -1;
}
// 4. 判断队空
public boolean isEmpty() {
return rear == front;
}
// 5. 判断队满
public boolean isFull() {
return rear + 1 == maxSize;
}
// 6. 添加数据(入队)
public void addQueue(int n) {
if (isFull()) {
System.out.println("对列已满,不能在加入数据~~~");
return;
}
rear++;
arr[rear] = n;
}
// 7. 获取数据(出队)
public int getQueue() {
if (isEmpty()) {
/*System.out.println("队列已空,不能再取数据");
return xxx;*/
throw new RuntimeException("队列已空,不能再取数据");
}
front++;
return arr[front];
}
// 8. 显示队列数据
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]);
}
}
// 9. 显示队头数据
public int headQueue() {
if (isEmpty()) {
// 在有返回值的情况下,需要显示提示信息,可以通过抛出异常的方式来显示
// 抛出异常后,直接结束方法的执行
throw new RuntimeException("队列是空的,没有数据~~~");
}
// 这里只是显示,不是获取,队头的位置不能变
return arr[front+1];
}
}
最大容量 maxSize:队列的最大容量是队列数据总数+1
队头 front:队列中的第一个数据
队尾 rear:队列中最后一个数据的后面一个位置
队空:rear==front
队满:(rear+1)%maxSize == front
队列中有效元素的个数:(rear+maxSize-front)%maxSize
使用环形队列时,数组里多加了一个空位置(作为约定),实际可容纳的最大数据个数 = (数组长度 -1)
注意:
i < front + size()
。防止当 rear < front
时,无法进行判断。i
自动递增即可,通过 i%maxSize
来获取对应下标的数据。完整代码:
package com.Queue_02;
import javax.sound.midi.Soundbank;
import java.util.Scanner;
public class CircleArrayQueueDemo {
/**
* 1. 创建一个CircleArrayQueue的类
* 2. 添加属性
* 3. 写构造方法,初始化属性
* 4. 判空
* 5. 判满
* 6. 向循环队列中添加数据
* 7. 从循环队列中取数据
* 8. 显示队列数据
* 9. 显示队头数据
* 10. 测试
*/
public static void main(String[] args) {
// 10. 测试
CircleArrayQueue queue = new CircleArrayQueue(3);
Scanner scanner = new Scanner(System.in);
char key = ' ';
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):退出队列");
key = scanner.next().charAt(0);
switch (key) {
case 's':
queue.showQueue();
break;
case 'a':
System.out.print("请输入要添加的数据:" );
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'g':
try {
int res = queue.getQueue();
System.out.printf("从队列中获取的数据是:%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res = queue.headQueue();
System.out.printf("队头数据是:%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("退出程序~~~");
}
}
class CircleArrayQueue{
// 1. 创建一个CircleArrayQueue的类
// 2. 添加属性
private int maxSize;
private int front;
private int rear;
private int[] arr;
// 3. 写构造方法,初始化属性
public CircleArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize + 1;
front = 0;
front = 0;
arr = new int[maxSize];
}
// 4. 判空
public boolean isEmpty() {
return rear == front;
}
// 5. 判满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
// 6. 向循环队列中添加数据
public void addQueue(int n) {
if (isFull()) {
System.out.println("循环数组已满,不能再添加数据~~~");
return;
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
// 7. 从循环队列中取数据
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("循环数组为空,不能再取数据~~~");
}
int oFront = front;
front = (front + 1) % maxSize;
return arr[oFront];
}
// 8. 显示队列数据
public void showQueue() {
if (isEmpty()) {
System.out.println("循环数组为空,没有数据可供显示~~~");
return;
}
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d] = %d\n", i % maxSize, arr[i % maxSize]);
}
}
// 数组中有效元素的个数
public int size() {
return (rear + maxSize - front) % maxSize;
}
// 9. 显示队头数据
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("循环数组为空,没有任何数据可供显示~~~");
}
return arr[front];
}
}