定义
-
队列是一个有序列表,可以用数组或是链表来实现。
-
遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
-
示意图:(使用数组模拟队列示意图)
队列
图解思路
判断队列为满、为空的思路
-
队列为满
-
由于使用数组模拟队列 数组从0开始计算,故数组下标最大值为maxSize-1
-
rear为队列后端下标 当队列后端下标为maxSize-1时 队列满
-
-
队列为空
当数组前端和后端重合时,队列为空
代码实现
/**
* 这是一个队列对象 有以下私有属性
* maxSize 队列最大容量
* front 指向队列前端
* rear 指向队列后端
* front 会随着数据输出而改变,而 rear则是随着数据输入而改变
* arr 是队列信息的存储方式
*/
class ArrayQueue {
private final int maxSize;
private int front;
private int rear;
private final int[] arr;
/**
*对象的公有构造器
* 初始化的队列front和rear都为-1
* @param arrMaxSize 队列最大容量
*/
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1;
rear = -1;
}
/**
* 判断队列是否已满
* @return
*/
public boolean isFull() {
return rear == maxSize - 1;
}
/**
* 判断队列是否为空
* @return
*/
public boolean isEmpty() {
return front == rear;
}
/**
* 往队列中加入元素
* @param n 为元素
*/
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列已满!");
return;
}
arr[++rear] = n;
}
/**
* 从队列中取出元素
* @return 返回先入元素。队列遵循先入先出原则
*/
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空!");
}
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]);
}
}
/**
* 返回队列头元素
* @return
*/
public int peek() {
if (isEmpty()) {
throw new RuntimeException("队列为空!");
}
return arr[front + 1];
}
}
环形队列
概述
对前面的数组模拟队列的优化,充分利用数组。因此将数组看做是一个环形的。(通过取模的方式来实现即可)
图解思路
思路如下
-
front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素,front 的初始值 = 0
-
rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定,rear 的初始值 = 0
-
当队列满时,条件是 (rear + 1) % maxSize == front 【满】
-
对队列为空的条件, rear == front 空
-
当我们这样分析, 队列中有效的数据的个数 (rear + maxSize - front) % maxSize // rear = 1 front = 0
-
我们就可以在原来的队列上修改得到,一个环形队列
代码实现
/**
* 这是一个环形队列对象 有以下私有属性
* maxSize 队列最大容量
* front 指向队列的第一个元素
* rear 指向队列的最后一个元素的后一个位置
* front 会随着数据输出而改变,而 rear则是随着数据输入而改变
* 输出数据时front = (front + 1)% maxSize;rear = ( rear + 1)% maxSize;
* arr 是队列信息的存储方式
*/
class CircleArrayQueue {
private final int maxSize;
private int front;
private int rear;
private final int[] arr;
/**
* 对象的公有构造器
* 初始化的队列front和rear都为0
*
* @param arrMaxSize 队列最大容量
*/
public CircleArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = 0;
rear = 0;
}
/**
* 当队列满时,条件是 (rear + 1) % maxSize == front
*
* @return
*/
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
/**
* 对队列为空的条件, rear == front
*
* @return
*/
public boolean isEmpty() {
return front == rear;
}
/**
* 往队列中加入元素
*
* @param n
*/
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列已满!");
return;
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
/**
* 从队列中取出元素
*
* @return 返回先入元素。队列遵循先入先出原则
*/
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空!");
}
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
/**
* 遍历并打印队列
*/
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]);
}
}
/**
* 返回队列中有效的数据的个数
* (rear + maxSize - front) % maxSize
*
* @return 有效的数据的个数
*/
public int size() {
return (rear + maxSize - front) % maxSize;
}
/**
* 返回队列头元素
*
* @return
*/
public int peek() {
if (isEmpty()) {
throw new RuntimeException("队列为空!");
}
return arr[front];
}
}