2.2 队列(使用数组实现队列)
2.2.1 队列的一个使用场景
银行排队的案例:先到先排队,先处理业务
2.2.2 队列介绍
-
队列是一个有序列表,可以用数组或是链表来实现
-
遵循先进先出的原则。即:先进入队列的数据,要先取出,后存入的要后取出
-
示意图:
-
-
rear指向队列尾部的数据,front指向队列头部数据的前一位,因为队列从0开始,所以队列的最后一个位置为队列的最大容量 maxSize-1
2.2.3 数组模拟队列思路
-
队列本身是有序列表,若使用数组的方式来存储队列,则队列数组的声明如上图,其中 maxSize 是该队列的最大容量
-
因为队列的输入输出分别是从前后端来处理,因此需要两个变量 front 及 rear来分别记录队列的前后端的下标,front会随着数据的输出发生改变,rear会随着队列的数据的输入而改变,如上图所示
-
当我们将数据存入队列时(addQueue),addQueue的处理需要有两个步骤:
-
将尾指针往后移:rear+1
-
判断队列是否已满,即尾指针rear是否到达最大值maxSize-1的位置,若队列未满,则将数据存入rear所指的数组元素中
-
代码实现:
public class ArrayQueueDemo { 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(add): 添加数据到队列"); System.out.println("g(get): 从队列取出数列"); System.out.println("h(head): 查看队列头的数据"); //接受字符 key = scanner.next().charAt(0); switch (key){ case 's': arrayQueue.showQueue(); break; case 'e': scanner.close(); loop = false; break; case 'a': System.out.println("请输入一个数:"); int i = scanner.nextInt(); arrayQueue.addQueue(i); break; case 'g': arrayQueue.getQueue(); break; case 'h': System.out.println("队列头的数据为:"); arrayQueue.getFront(); break; default: break; } } System.out.println("程序退出"); } } /** * 使用数组模拟队列 */ class ArrayQueue{ /** * 表示数组的最大容量 */ private int maxSize; /** * 队列头 */ private int front; /** * 队列尾 */ private int rear; /** * 用于存放队列中的数据,模拟队列 */ private int[] arr; /** * 创建队列的构造器 */ public ArrayQueue(int maxSize){ this.maxSize = maxSize; arr = new int[maxSize]; //指向队列头部,指向队列头的前一个数据 front = -1; //指向队列尾部,直接指向队列尾部的数据 rear = -1; } /** * 判断队列是否满 */ public boolean isFull(){ return rear + 1 == maxSize; } /** * 判断队列是否为空 */ public boolean isEmpty(){ return rear == front; } /** * 添加数据到队列 */ public void addQueue(int m){ //判断队列是否满 if (isFull()){ System.out.println("队列已满,不能再添加数据"); return; } //rear后移,并将数据存入其中 rear++; arr[rear] = m; } /** * 出队列,获取队列的数据 */ public void getQueue(){ //判断队列是否为空 if (isEmpty()){ System.out.println("队列为空,没有数据可以获取了"); return; } //front后移 front++; System.out.println("获取到的数据为:"+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 void getFront(){ if (isEmpty()){ System.out.println("队列为空,没有数据可以获取了"); return; } System.out.println("队列的头数据为:"+arr[front+1]); } }
问题分析并优化:
-
问题:目前数组使用一次就不能再次使用,没有达到复用的效果
-
将这个数组使用算法,改进成一个环形数组(下一期)