1、队列
- 队列是一个有序列表,可以用数组或链表来实现;例如银行排队系统,就是队列的应用;
- 遵循先入先出的原则。
- 如果用数组来存储队列的数据,则用maxSize来表示队列的最大容量,用front和rear来表示队列前后端的下标,front会随着数据输出而改变,rear会随着数据输入而改变。
2、数组队列
/*
本文件:用数组创建队列。
*/
package DataStructures;
import java.util.Scanner;
public class ArrQueue {
public static void main(String[] args) {
//创建数组队列
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(show):添加数据到队列");
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.println("请输入一个数据:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g': //取数据,如果成功,就打印取出的数据,如果没取成功,就抛出异常,用catch打印异常数据
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 final int maxSize;//表示数组的最大容量
private int front; //队列头
private int rear; //队列尾
private final int[] arr; //模拟队列存放数据
//创建队列构造器
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
//初始化的时候front和rear都是-1
front = -1; //front=-1时,指向队列头的前一个位置
rear = -1; //rear=-1时,指向队列的最后一个数据
}
// 判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//添加数据到队列
public void addQueue(int n) {
//先判断队列是否满
if (isFull()) {
System.out.println("队列满,不能加入数据");
return;
}
rear++;//让队尾标致rear后移一位
arr[rear] = n;
}
//获取队列的数据,即出队列
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()) {
throw new RuntimeException("队列空,没有数据");
}
return arr[front + 1];
}
}
3、数组环形队列
普通的数组队列,头部数据取出后,其空间没有被释放,为了实现对空间的“复用”,所以引入数组环形队列。
使用数组创建环形队列的思路如下:
- front变量的含义做一个调整:front指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值=0;
- rear变量的含义也做一个调整:rear指向队列最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值=0;
- 队列满的条件为:(rear+1)%maxSize == front;
- 队列空的条件为:rear == front;
- 队列中有效数据的个数为:(rear+maxSize-front)%maxSize
/*
本文件:用数组创建环形队列。
*/
package DataStructures;
import java.util.Scanner;
public class CircleArrayQueue {
public static void main(String[] args) {
//创建环形队列
CircleArrQueue circleArrqueue = new CircleArrQueue(4);//该环形队列的有效数据位为4-1=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(show):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头数据");
key = scanner.next().charAt(0);//接收一个字符
switch (key) {
case 's':
circleArrqueue.showQueue();
break;
case 'a':
System.out.println("请输入一个数据:");
int value = scanner.nextInt();
circleArrqueue.addQueue(value);
break;
case 'g': //取数据,如果成功,就打印取出的数据,如果没取成功,就抛出异常,用catch打印异常数据
try {
int res = circleArrqueue.getQueue();
System.out.printf("取出的数据是:%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res = circleArrqueue.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 CircleArrQueue {
private final int maxSize;
private int front;
private int rear;
private final int[] arr;
public CircleArrQueue(int arrMaxSize) {
maxSize = arrMaxSize;
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()) {
System.out.println("队列满,不能加入数据");
return;
}
//直接将数据加入
arr[rear] = n;
//将rear后移一位,但要考虑取模,防止溢出
rear = (rear + 1) % maxSize;
}
//获取队列的数据,即出队列
public int getQueue() {
//判断队列是否空
if (isEmpty()) {
//通过抛出异常来处理
throw new RuntimeException("队列为空,不能取数据");
}
//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开始遍历
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()) {
throw new RuntimeException("队列空,没有数据");
}
return arr[front];
}
//求出当前队列有效数据的个数
public int size() {
return (rear + maxSize - front) % maxSize;
}
}