队列介绍与实现
1. 队列定义
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。简言之,就是先进先出(First In First Out)。
2. 使用数组模拟队列思想
2.1 思想
- 当插入数据到队列数组时,先判断该队列是否已满,满则不能插入,否则可以插入队列。此时队尾(rear)先往后移动(+1),然后插入数据。
- 当队列取出数据的时,先判断该队列是否已空,空则不能去数据,否则可以取出数据。此时队头(front)先往后移动(+1),然后取出数据。
- 判断队列是否为空:当队头和队尾相等时,即
front==rear
- 判断队列是否为满:当队尾等于(队列数组最大值-1)时,即
rear==maxSize-1
;
2.2 涉及的变量说明
maxSize
:表示队列数据最大容量,即队列可有多少个元素。
front
:表示队列头
rear
:表示队列尾
arr[]
:用于存放数据,模拟队列的数据
2.3 实现过程思想
2.3.1 队列初始化
首先要创建存放n个容量数据的数组arr[n]
,并将front=-1;rear=-1
例如创建4个数据的队列,图如下:
在java代码中,可以使用构造函数初始化队列数据,如下:
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[this.maxSize];
front = -1;
rear = -1;
}
2.3.2 添加数据在队列
队尾rear
先后移,然后赋值到队列 arr[rear]=a;
代码过程:
// 添加数据到队列
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列满,不能加入数据~");
return;
}
rear++;// 让rear 后移
// arr[++rear];
arr[rear] = n;
System.out.println("添加成功~");
}
2.3.3 取出队列数据
队头front先往后移front++
,然后获取返回 arr[front];
代码过程:
// 获取队列的数据,出队列
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,不能取数据");
}
front++; // front 后移
// arr[++front];
return arr[front];
}
3.问题与总结
3.1 front和rear初始化的值
问:front和rear初始化的值为什么是-1呢?
答:front
和rear
的初始化的值可以是0,其中为-1的情况是方便队头/队尾和队列数组下标对应;其中值为0或-1都可以的。当front=0,rear=0
时,添加/取出数据时,先是添加/取数据,后移动rear/front
;且判断队列满条件应改变为rear==maxSize
。
3.2 队列数组的局限
队列数组使用一次就不能用,没有达到复用的效果且浪费内存空间。因此引出循环队列来解决这个问题。
https://blog.csdn.net/weixin_41561168/article/details/120266798
4.完整实现代码
public class ArrayQueueDemo {
public static void main(String[] args) {
ArrayQueue queue = new ArrayQueue(4);
int key = 0;
Scanner scanner = new Scanner(System.in);
boolean loop = true;
System.out.println("\t 1: 显示队列");
System.out.println("\t 2: 添加数据到队列");
System.out.println("\t 3: 从队列取出数据");
System.out.println("\t 4: 查看队列头的数据");
System.out.println("\t 5: 退出程序");
while (loop) {
key = scanner.nextInt();
switch (key) {
case 1:
queue.showQueue();
break;
case 2:
System.out.println(">>输入一个数:");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 3:
try {
int res = queue.getQueue();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 4:
try {
int res = queue.headQueue();
System.out.printf("队列头的数据是%d\n", res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 5:
scanner.close();
loop = false;
break;
default:
System.out.println("请输出有效数字~");
break;
}
}
System.out.println("程序退出~~");
}
}
//使用数组模拟队列-编写一个ArrayQueue类
class ArrayQueue {
private int maxSize; // 表示数组的最大容量
private int front; // 队列头
private int rear; // 队列尾
private int[] arr; // 该数据用于存放数据,模拟队列
// 创建队列的构造器
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[this.maxSize];
front = -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];
arr[rear] = n;
System.out.println("添加成功~");
}
// 获取队列的数据,出队列
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,不能取数据");
}
front++; // front 后移
// arr[++front];
return arr[front];
}
// 显示队列的所有数据
public void showQueue() {
if (isEmpty()) {
System.out.println("队列空的,没有数据~~");
return;
}
for (int i = front + 1; i < rear + 1; i++) {
System.out.printf("arr[%d]=%d\n", i, arr[i]);
}
}
// 显示队列的头数据,注意不是取出数据
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,没有数据~~");
}
return arr[front + 1];
}
}