一.什么是队列?
队列(Queue)跟栈(Stack)一样是一种线性数据结构,但是不同于栈的先入后出,队列中的元素只能先入先出(First In First Out, 简称 FIFO),也就是元素只能从一端进,另一端出。
通常,队列的出口端叫做 队头(front),入口端叫做 队尾(rear);数据元素进入队列的过程就叫做 入队,出队列的过程就叫做 出队。队列中数据元素的进出要遵从 “先进先出”的原则。
二.队列的实现
队列的实现有以下两种方式:
- 顺序队列:数组来实现的队列结构。
- 链式队列:用链表来实现的队列结构。
三.队列的应用
- 实际生活中比较常见的,每次排队在奶茶店买奶茶都应该是一个队列。毕竟在前面的肯定先买到。
- 在大学里,如果所有的电脑终端都被占用了,并且由于资源是有限的,学生们必须在一个等待表上签字,在终端上登陆时间最长的学生将会首先被强制离开,而等待时间最长的学生将是下一个被允许使用电脑的用户。
四.数组实现单向队列
因为队列的进队和出队是分别从队头和队尾来进行的,所以需要两个变量 front 及 rear 分别记录队列队头和队尾的下标,front 会随着数据出队而改变,而 rear 则是随着数据入队而改变。
1.入队
- 当数据存入队列时,称为 " 入队(addQueue) ";入队 尾指针需要向后移,即: rear + 1。
- 这里要注意,当队列已经是满的时候,是无法入队的,即:若队尾指针 rear 小于 队列的最大下标 - 1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。
2.出队
- 当数据出队时,出队 头指针需要向后移,即:front + 1。
五.特殊情况处理
- 队列为空,即 front == rear。
// 判断队列是否为空
public boolean isEmptyQueue() {
return rear == front;
}
队列是否已满,当尾指针等于队列最大下标 - 1时判断为满,即:rear == maxSize - 1。
// 判断队列是否已满
public boolean ifFullQueue() {
return rear == maxSize - 1;
}
六.代码
import java.util.Queue;
import java.util.Scanner;
import javax.management.RuntimeOperationsException;
public class ArrayQueueDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayQueue arrayQueue = new ArrayQueue(5); // 队列长度设置 5
char input = ' '; // 用户输入
boolean loop = true;
// 菜单
while (loop) {
System.out.println("s(showQueue): 打印队列");
System.out.println("a(addQueue): 添加数据-入队");
System.out.println("g(getQueue): 取出数据-出队");
System.out.println("h(showFront): 查看队头的数据");
System.out.println("e(exit): 退出程序");
// 获取用户输入的字符
input = scanner.next().charAt(0);
switch (input) {
case 's':
arrayQueue.showQueue();
break;
case 'a':
System.out.println("输入一个数");
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.showHeadQueue();
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; // 指向队尾的数据(队列的最后一个数据)
}
// 判断队列是否已满
public boolean ifFullQueue() {
return rear == maxSize - 1;
}
// 判断队列是否为空
public boolean isEmptyQueue() {
return rear == front;
}
public void addQueue(int n) {
// 先判断队列是否已经满
if (ifFullQueue()) {
System.out.println("队列已经满了,不能继续添加数据");
return;
}
rear++;
arr[rear] = n;
}
// 出队
public int getQueue() {
// 先判断队列是否为空
if (isEmptyQueue()) {
// 抛出异常
throw new RuntimeException("队列为空, 不能获取数据");
}
front++;
return arr[front];
}
public void showQueue() {
// 遍历队列
// 以及判断是否为空
if (isEmptyQueue()) {
// 抛出异常
System.out.println("队列为空,不能获取数据");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d] = %d\n", i, arr[i]);
}
}
// 显示队头数据元素
public int showHeadQueue() {
// 先判断队列是否为空
if (isEmptyQueue()) {
// 抛出异常
throw new RuntimeException("队列为空,不能获取数据");
}
return arr[front + 1];
}
}