使用Java实现队列(数组)
1、首先定义这个队列的数据结构
class Queue {
// 队列的容量
private int size;
// 头指针 指向队列的第一个元素,初始值为 0
private int front;
// 尾指针 指向队列的最后一个元素的后一个位置,初始值为 0
private int rear;
// 队列 存放数据,模拟队列
private int[] arr;
}
说明:
- size:这个队列的大小
- front:头指针,这个指针永远指向队列的头元素,初始值为 0
- rear:尾指针,这个指针指向队列的最后一个元素的后一个元素,初始值为 0 ,所以这个队列的可用大小 = size - 1
- arr:表示这个队列
为了便于理解,分别画出了队列为空,有值,队列满的三种状态,如下图所示:
如图所示,当队列为空时,rear和front都为零(左图),当队列中有元素时rear指向队列最后一个元素的后一个位置(中间图),右图表示队列已满。
2、 队列中几种特殊状态的判断
- 为空:当 rear = front 时,队列为空
- 为满:当 (rear + 1) % size = front 时,表示队列已满
- 添加数据:当添加数据的时候,rear 指针应该后移一位,所以 rear = (rear + 1) % size
- 取出数据:取出数据的时候,front 指针也应该后移一位,所以 front = (front + 1) % size
- 队列中的元素个数:队列中的元素个数 = (rear + size - front) % size
3、重要方法说明
- 添加数据方法
public void add(int data) {
if (isFull()) {
System.out.println("队列已满,不能添加数据~~");
return;
}
arr[rear] = data;
// 将指针后移
rear = (rear + 1) % size;
}
首先判断队列是否为满( isFull() 方法在最后代码中会给出),然后向数组中添加值,最后把 rear 指针向后移动一位,因为考虑到环形队列的情况,在计算 rear 指针的时候一定要取模,不然会数组越界。为了便于理解,请看下图:
作图表示一个队列,当再添加一个数据的时候,这时 rear 指针应该后移一位,但是如果 rear 直接加1,则会导致数组下标越界,所以,rear应该指向0,如右图所示。所以 rear = (rear + 1) % size
- 取出数据
public int get() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取出数据~~");
}
int data = arr[front];
front = (front + 1) % size;
return data;
}
首先判断队列是否为空(isEmpty() 方法会再后面一并给出,然后取出一个数据,然后 front 指针应该后移指向下一个数据,最后返回数据。在指针后移的时候也应该考虑环形队列的问题,不然也会导致数组下标越界。为了便于理解,请看下图。
如图所示,左图为原始队列,当取出一个数据的时候 front 移向下一个数据,这时,如果只是 front + 1的话,会导致数组下标越界异常,所以这时 front = (front + 1) % size
- 返回队列中有效数据的个数
public int size() {
return (rear + size - front) % size;
}
队列中有效数据的计算公式:(rear + size - front) % size
- 显示队列中的元素
public void show() {
if (isEmpty()) {
System.out.println("队列为空,没法显示数据~~");
return;
}
// 遍历取出队列中的元素
// 思路: 从 front 开始遍历,取出后面 (队列大小)个元素
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % size, arr[i % size]);
}
}
遍历的思路就是:从头指针开始遍历,取出后面 (队列大小)个元素,在取出数组中元素的时候,记得取模,即arr[i % size]。不然会数组越界。
4、完整代码:
package com.gamazing.queue;
import java.util.Scanner;
public class ArrayQueue {
public static void main(String[] args) {
// 初始化一个队列,队列大小为4,可用大小为3
Queue queue = new Queue(4);
// 接收输入
char c = ' ';
Scanner scanner = new Scanner(System.in);
boolean flag = true;
while (flag) {
/*Runtime.getRuntime().exit(1);*/
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): 查看队列头的数据");
c = scanner.next().charAt(0);// 接收一个字符
switch (c) {
case 's':
queue.show();
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
queue.add(value);
break;
case 'g': // 取出数据
try {
int res = queue.get();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h': // 查看队列头的数据
try {
int res = queue.showHead();
System.out.printf("队列头的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e': // 退出
scanner.close();
flag = false;
break;
default:
break;
}
}
System.out.println("程序退出~~");
}
}
class Queue {
// 队列的容量
private int size;
// 头指针 指向队列的第一个元素,初始值为 0
private int front;
// 尾指针 指向队列的最后一个元素的后一个位置,初始值为 0
private int rear;
// 队列 存放数据,模拟队列
private int[] arr;
// 构造方法
public Queue(int arraySize) {
this.size = arraySize;
arr = new int[size];
front = 0;
rear = 0;
}
// 判断队列是否满
private boolean isFull() {
return (rear + 1) % size == front;
}
// 判断队列是否为空
private boolean isEmpty() {
return rear == front;
}
// 添加数据
public void add(int data) {
if (isFull()) {
System.out.println("队列已满,不能添加数据~~");
return;
}
arr[rear] = data;
// 将指针后移
rear = (rear + 1) % size;
}
// 取出数据
public int get() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取出数据~~");
}
int data = arr[front];
front = (front + 1) % size;
return data;
}
// 返回队列中有效数据的个数
public int size() {
return (rear + size - front) % size;
}
// 显示队列
public void show() {
if (isEmpty()) {
System.out.println("队列为空,没法显示数据~~");
return;
}
// 遍历取出队列中的元素
// 思路: 从 front 开始遍历,取出后面 (队列大小)个元素
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % size, arr[i % size]);
}
}
// 显示头元素
public int showHead() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取出数据~~");
}
return arr[front];
}
}
第一次使用 Java 来实现队列,如果有问题,或者更好的办法,请大家及时指出。