数据结构之环形队列
数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组,因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:
尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front 满]
rear == front [空]
测试示意图:
代码实现
package cn.tedu.queue; import java.util.Scanner; /** * @ClassName CircleArrayQueueDemo * @Description * @Author keke * @Time 2022/1/3 14:47 * @Version 1.0 */ public class CircleArrayQueueDemo { public static void main(String[] args) { // 初始化一个队列 // 有效数据是 maxSize - 1 CircleArrayQueue circleArrayQueue = new CircleArrayQueue(4); // 接收用户输入 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': circleArrayQueue.showQueue(); break; case 'a': System.out.print("输出一个数:"); circleArrayQueue.addQueue(scanner.nextInt()); break; case 'g': try { System.out.println("取出的数据是:" + circleArrayQueue.getQueue()); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'h': try { System.out.println("队列头的数据是:" + circleArrayQueue.headQueue()); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'e': scanner.close(); loop = false; break; default: break; } } System.out.println("程序退出"); } } class CircleArrayQueue { /** * 数组的最大容量 */ private int maxSize; /** * 队列头: * front 变量的含义做一个调整: front 就指向队列的第一个元素, * 也就是说 arr[front] 就是队列的第一个元素,front 的初始值 = 0 * */ private int front; /** * 队列尾: * rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. * 因为希望空出一个空间做为约定,rear 的初始值 = 0 */ private int rear; /** * 该数据用于存放数据,模拟队列 */ private int[] arr; public CircleArrayQueue(int maxSize) { this.maxSize = maxSize; arr = new int[maxSize]; } /** * 判断队列是否满 */ public boolean isFull() { return (rear + 1) % maxSize == front; } /** * 判断队列是否为空 * * @return */ public boolean isEmpty() { return rear == front; } /** * 添加数据到队列 * * @param n */ public void addQueue(int n) { // 判断队列是否满 if (isFull()) { System.out.println("队列满,不能加入数据"); return; } // 直接将数据加入 arr[rear] = n; // 将 rear 后移,这里必须考虑取模 rear = (rear + 1) % maxSize; } /** * 获取队列的数据,出队列 * @return */ public int getQueue() { // 判断队列是否为空 if (isEmpty()) { // 通过异常抛出 throw new RuntimeException("队列空,不能取数据"); } // 这里需要分析 front 是指向队列的第一个元素 // 1.先把 front 对应的值保存到一个临时的变量 // 2.将 front 后移,考虑取模 // 3.将临时保存的变量返回 int value = arr[front]; front = (front + 1) % maxSize; return value; } /** * 显示队列的所有数据 */ public void showQueue() { // 遍历 if (isEmpty()) { System.out.println("队列空的,没有数据"); return; } // 从 front 开始遍历,遍历多少个元素 for (int i = front; i < front + size(); i++) { System.out.printf("arr[%d] = %d\n", i % maxSize, arr[i % maxSize]); } } /** * 求出当前队列有效数据的个数 * @return */ public int size(){ return (rear + maxSize - front) % maxSize; } /** * 显示队列的头部,注意不是取出数据 * * @return */ public int headQueue() { // 判断 if (isEmpty()) { throw new RuntimeException("队列空的,没有数据"); } return arr[front]; } }
截图