环形数组队列问题解析

初学算法被环形数组队列问题折腾了一上午,思来想去终于理清了思路。

1     private int maxsize;    //数组的最大容量
2     private int rear;       //指向队列最后一个元素的后一个位置
3     private int front;      //队列首部,指向队列的第一个元素
4     private int[] arr;      //该数据用于存放数据,模拟队列

 

  这里是一些需要用到的属性。

  数组的最大容量不必说了,就是数组最大能够承装的数据值。但是需要注意的是,在此解法中,这里定义的最大容量在实际运行时是会减一的。即 ActualLength = maxsize - 1;

  front即队列头部位置第一个元素在数组中的索引;

  rear指向数组最后一个元素之后一个位置,指向的位置往往可以看作空,这也是为什么定义的最大容量在实际情况下会减一的原因。这样定义是为了方便判断队列是否为满或空

  

1     //判断队列是否满
2     public boolean isFull() {
3         return (rear + 1) % maxsize == front;
4     }

  判断队列是否满员的情况可以看成判断指针front和指针rear是否相邻,若队伍满员,那么rear+1则正好会和front的指针重合。此时为了避免数组角标越界进行取模运算,返回true。

 

1     //判断队列是否为空
2     public boolean isEmpty() {
3         return rear == front;
4     }

  判断队列是否为空,很简单两指针若刚好重合则说明队列为空

 

 1     //添加数据到队列
 2     public void addQueue(int n) {
 3         //判断队列是否满员
 4         if (isFull()) {
 5             System.out.println("队列已满,无法添加数据");
 6             return;
 7         } else {
 8             //直接将数据加入
 9             arr[rear] = n;
10             //将rear后移,这里必须考虑取模
11             rear = (rear + 1) % maxsize;
12         }
13     }

  向队列中添加数据,首先判断队伍是否满员,若未满员则进入else语句。首先将需要加入的n值添加进当前数组rear索引位置,然后需要将rear后移,因为需要考虑环形问题,若rear此时刚好处于数组的最尾部,则它需要循环返回数组首端,即将rear+1后取模。

 

 1     //取出队列头部的数据,出队列
 2     public int getQueue() {
 3         //判断队列是否为空
 4         if (isEmpty()) {
 5             //通过抛异常处理
 6             throw new RuntimeException("队列为空");
 7         } else {
 8             //分析出front是指向队列的第一个元素
 9             //1. 先把front对应的值保留到一个临时变量
10             //2. 将front后移,考虑取模
11             //3. 将临时保存的变量返回
12             int value = arr[front];
13             front = (front + 1)% maxsize;
14             return value;
15         }
16     }

  此方法先取出当前头部的数值,然后将其抹去,同时需要将front指针后移一位。这里和上面添加数据到队列类似,但是是针对front指针的操作。同样需要考虑数组角标越界问题。

 1     //显示队列的所有数据
 2     public void showQueue() {
 3         //遍历
 4         if (isEmpty()) {
 5             System.out.println("队列为空,无数据");
 6         } else {
 7             //思路:从front开始遍历,遍历多少个元素
 8             for (int i = front; i < front + size(); i++) {
 9                 System.out.printf("arr[%d] = %d\n", i % maxsize, arr[i % maxsize]);
10             }
11         }
12     }
13 
14     //求出当前队列有效数据的个数
15     public int size(){
16         return (rear + maxsize - front) % maxsize;
17     }

  显示所有数据需要和获取有效数据的方法共同使用,因为遍历数组所有数据需要从头部开始,也就是front指针处,遍历长度即为size,但是由于遍历是从front开始的,需要前面加上front。

  (rear-front+maxsize)%maxsize可以求出当前从front到rear的有效长度。

 

  

 

posted @ 2021-03-19 20:47  Carln  阅读(88)  评论(0编辑  收藏  举报