一、问题引出
原来的,数组模拟队列,使用一次之后就不能用了,没有达到复用的目的。将队列进行取模,从而,形成一个环形队列。
队列,与环形队列的区别,队列的front指针,指向第一个元素的,前一个位置。而环形队列front指针,指向第一个元素位置。队列的rear指针,指向队列的,最后一个位置。而环形队列的rear指针,指向环形队列最后一个元素的,后一个位置。空出一个位置作为约定(预留空间)
图例:
二、重要代码解析
判满和判空的条件: 当(rear+1)%maxSize==front 时队列为满
当rear=3,(3+1)%4=0 front=0 队列满
当rear==front队列为空
rear与front相等,也就是头指针,与尾指针重合,代表没有元素,队列为空
求当前元素个数
(rear+maxSize-front)%maxSize
参看以下图例
图例:
三、代码实现:
package linkedlist; import java.util.Scanner; /** * @author shkstart * @create 2021-08-05 10:29 */ public class CircleArrayDemo{ public static void main(String[] args) { //创建一个队列 ArrayQueue queue = new ArrayQueue(3); queue.showQueue(); queue.addQueue(1); queue.showQueue(); queue.getQueue(); queue.showQueue(); } } //环形数组模拟环形队列类 class CircleArray{ private int maxSize;//数组的最大容量 //front指向队列的第一个元素,arr[front]就是队列的第一个元素 //front的初始值=0 private int front; //rear 指向队列的最后一个元素的后一个位置,留出一个空间做约定 //rear 的初始值=0 private int rear;//队列尾 private int[] arr;//该数据用于存放数据,模拟队列 //构造器 public CircleArray(int arrMaxSize) { this.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; } //获取队列的数据,出队列 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]); } } //求当前元素的个数 public int size(){ //rear=2 //front=1 //maxsize=3 return (rear+maxSize-front)%maxSize; } //显示队列的头数据,不是取出数据 public int headQueue(){ if(isEmpty()){ System.out.println("队列为空"); } return arr[front]; } }