使用场景
java根据队列的数据结构封装以下的队列:并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue
基本介绍
- 队列是-一个有序列表,可以用数组或是链表来实现。
2)遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
3)示意图: (使用数组模拟队列示意图)
数据模拟队列
模拟思路分析
- 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中maxSize 是该队
列的最大容量。 - 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front 及rear 分别记录队列前后端的下标,
front会随着数据输出而改变,而rear则是随着数据输入而改变,如图所示:
代码实现
/**
* 数组模拟队列
*/
class ArrayQueue {
/**
* 表示数组里最大容量
*/
private int maxSize;
/**
* 队列头标识,初始化为-1
*/
private int front;
/**
* 队列尾部标识,初始化为-1
*/
private int rear;
/**
* 存放数据,使用数组模拟队列
*/
private int[] arrayQueue;
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arrayQueue = new int[maxSize];
front = -1;
rear = -1;
}
public boolean isFull() {
return rear + 1 == maxSize;
}
public boolean isEmpty() {
return rear == front;
}
public void addQueue(int n) {
if (isFull()) {
System.out.println("===队列已满,无法插入===");
return;
}
arrayQueue[++rear] = n;
}
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("===队列为空,数据无法取出===");
}
return arrayQueue[++front];
}
public void showQueue() {
if (isEmpty()) {
System.out.println("===队列为空,没有数据===");
return;
}
for (int i = 0; i < arrayQueue.length; i++) {
System.out.printf("arrayQueue[%d]=%d\n", i, arrayQueue[i]);
}
}
public int headQueue(){
if (isEmpty()) {
throw new RuntimeException("===队列为空,没有数据===");
}
return arrayQueue[front+1];
}
}
测试
public class ArrayQueueTest {
public static void main(String[] args) {
System.out.println("===测试数组模拟环形队列的案例===");
// 创建一个环形队列
ArrayQueue queue = new ArrayQueue(4); //说明设置4, 其队列的有效数据最大是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(add): 添加数据到队列");
System.out.println("g(get): 从队列取出数据");
System.out.println("h(head): 查看队列头的数据");
key = scanner.next().charAt(0);// 接收一个字符
switch (key) {
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'g': // 取出数据
try {
int res = queue.getQueue();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'h': // 查看队列头的数据
try {
int res = queue.headQueue();
System.out.printf("队列头的数据是%d\n", res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'e': // 退出
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出~~");
}
}
数组模拟环型队列
对前面的数组模拟队列的优化,充分利用数组.因此将数组看做是-一个环形的。(通过取模的方式来实现即可)
模拟思路分析
- 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的
时候需要注意(rear + 1) % maxSize== front满] - rear == front [空]
- 分析示意图:
代码实现
/**
* 数组模拟环型队列
*/
class CircleArrayQueue {
/**
* 表示数组里最大容量
*/
private int maxSize;
/**
* 队列头标识,初始化为0。位于当前队头
*/
private int front;
/**
* 队列尾部标识,初始化为0,最后一个元素的后一个位置
*/
private int rear;
/**
* 存放数据,使用数组模拟队列
*/
private int[] arrayQueue;
public CircleArrayQueue(int maxSize) {
this.maxSize = maxSize;
arrayQueue = new int[maxSize];
}
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;
}
arrayQueue[rear] = n;
rear = (rear + 1) % maxSize;
}
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空,数据无法取出");
}
int temp = arrayQueue[front];
front = (front + 1) % maxSize;
return temp;
}
public void showQueue() {
if (isEmpty()) {
System.out.println("===队列为空,没有数据===");
return;
}
for (int i = front; i < front + size(); i++) {
System.out.printf("arrayQueue[%d]=%d\n", i % maxSize, arrayQueue[i % maxSize]);
}
}
public int size() {
return (rear - front + maxSize) % maxSize;
}
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("===队列为空,没有数据===");
}
return arrayQueue[front];
}
}
测试
public class CircleArrayQueueTest {
public static void main(String[] args) {
//测试一把
System.out.println("测试数组模拟环形队列的案例~~~");
// 创建一个环形队列
CircleArrayQueue queue = new CircleArrayQueue(4); //说明设置4, 其队列的有效数据最大是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(add): 添加数据到队列");
System.out.println("g(get): 从队列取出数据");
System.out.println("h(head): 查看队列头的数据");
key = scanner.next().charAt(0);// 接收一个字符
switch (key) {
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'g': // 取出数据
try {
int res = queue.getQueue();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'h': // 查看队列头的数据
try {
int res = queue.headQueue();
System.out.printf("队列头的数据是%d\n", res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'e': // 退出
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出~~");
}
}