环形队列实例
基本定义:
int[] arr 是定义一个整型数组当队列
maxSize是数组的最大容量
(这里规定,满队列时元素的个数是maxSize-1)
front指向队列的第一个元素,也就是说 array[front] 是队列的第一个元素
rear指向队列的最后一个元素,初值为0
队列满的条件:(rear + 1) % maxSize == front
队列为空的条件: rear == front
代码
package com.zzfan.queue; import java.util.*; public class CircleArrayQueue { public static void main(String[] args) { System.out.println("测试数组环形队列"); //创建一个环形队列 CircleArray queue = new CircleArray(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 result = queue.getQueue(); System.out.printf("取出的数据是%d\n", result); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'h': try { int result = queue.headQueue(); System.out.printf("头部的数据是%d\n", result); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'e': scanner.close(); loop = false; break; default: break; } } System.out.println("程序退出"); } } class CircleArray { //数组的最大容量 private int maxSize; //front指向队列的第一个元素,也就是说arr[front]是队列的第一个元素 private int front; //rear指向队列的最后一个元素的最后一个位置,初值为0 private int rear; private int[] arr; //该数据用于存放数据,模拟队列 public CircleArray(int arrMaxSize) { maxSize = arrMaxSize; arr = 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; } //直接将数据加入 arr[rear] = n; //将rear后移,必须考虑取模 rear = (rear + 1) % maxSize; /* 这里手算了一下,实际取模就是想办法当rear和队列最大容量相等时,在加1就重新取到rear=1 有个通俗易懂的例子:跑步套圈 有一个环形跑道,假设,将环形跑道分割成10份。 front某时刻跑到第3格了,rear此时刻已经跑到第10格了。 那么rear继续往下跑的时候,会发现,跑的第“11格”(实际并不存在)其实就是第1格,是第二圈的第1格。 */ } //获取队列的中的数据 public int getQueue() { //判断队列是否空 if (isEmpty()) { //通过抛出异常来处理 throw new RuntimeException("队列为空,无法取出数据"); //throw可以直接return一个异常,不用再写return } //front指向队列的第一个元素 /* 1. 先把front对应的值保留到一个临时变量中 2. front后移,考虑取模 3. 将临时保存的变量返回 */ int value = arr[front]; //先获取数据,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]); } } //有效数据的个数 public int size() { return (rear + maxSize - front) % maxSize; /*添加数据变的是rear,取出数据变的是front,所以当在第一个位置插入数据时,rear=2,front=1。 所以,如果不考虑取模,那有效数据个数就是rear-front 考虑取模的话会出现一种情况,rear已经开始“跑第二圈”了,front还在“第一圈” */ } //显示队列头 public int headQueue() { //判断是否为空 if (isEmpty()) { throw new RuntimeException("队列为空,没有数据"); } return arr[front]; } }
(防止忘记,尽量将注释写的多了些,记得看注释)