环绕队列
队列含义:
队列是一个有序列表,可以是 数组或是链表来实现
遵循先入先出的原则,即先存入队列的数据要先取出,后存入的要后取出
数组模拟队列思路 队列本身是有序列表,使用数组的结构来存储队列的数据,maxSize是该队列的最大容量 因为队列的输出,输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标, front会随着数据输出而改变,而rear则是随着数据输入而改变
数组模拟环形队列思路 1front变量的含义做调整,front就指向队列的第一个元素,也就是说arr[front] 就是队列的第一个元素,front的初始值=0 2rear变量的含义做调整,real指向队列的最后一个元素的后一个位置,因为希望空出一个空间做约定,rear的初始值=0 3当队列满时,条件是[rear+1]%maxSize==front 4当队列为空时条件rear==front 5队列中有效的数据个数[rear+maxSize-front]%maxSize
问题1:为什么拿到%maxSize的值
因为数组是一个环形数组,当数组末尾存满,但数组开头的数据取出时,可以把数据接着存到空位。所以用到%maxSize
front代表的就是数组第一个值,rear代表数组最后一个值,此时的环形数组的坐标不代表它属于开头还是结尾
问题2:空队列rear==front和满队列[rear+1]%maxSize==front条件的不同点:
按照如上图示,real==front会有两种情况,为空或为满。我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。
如下图所示,我们就认为此队列已经满了,也就是说,我们不允许上图情况出现。
例子
package com.ujiuye.queue; import java.util.Scanner; public class CircleArrayQueue { public static void main(String[] args) { System.out.println("测试模型队列案例"); //数组长度为3,但是其中有一个是空的,所以最多能放两个数据 CircleArray queue = new CircleArray(3); Scanner sc = new Scanner(System.in); char key= ‘ ‘; boolean flag = true; while(flag) { 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],查看列头数据"); System.out.println("=================="); System.out.println("请输入您要进行的操作(请用缩写字母或英文回复!)"); key = sc.next().charAt(0); switch(key) { case ‘s‘: queue.showQueue(); break; case ‘a‘: System.out.println("请添加一个数值"); int n = sc.nextInt(); queue.addQueue(n); break; case ‘g‘: try { int res = queue.getQueue(); System.out.printf("取出的数值是%d\n",res); }catch(Exception e) { System.out.println(e.getMessage()); } break; case ‘h‘: try { int res = queue.headQueue(); System.out.printf("队列头数值是%d\n",res); }catch(Exception e) { System.out.println(e.getMessage()); } break; case ‘e‘: sc.close(); flag = false; break; default: break; } } } } class CircleArray{ //表示数组的最大容量 private int maxSize; //指向队列的第一个元素,arr[front] 就是队列的第一个元素,初始值为0 private int front; //指向队列中的最后一个元素的后一个位置,因为希望空出一个空间做约定,rear的初始值=0 private int rear; //用来存储数据,模拟队列 private int[] arr; public CircleArray(int maxSize) { this.maxSize = maxSize; arr = new int[maxSize]; } //当队列满时,条件是[rear+1]%maxSize==front public boolean isFull() { return (rear+1)%maxSize == front; } //当队列为空时条件rear==front public boolean isEmpty() { return rear == front; } //往队列里添加数据 public void addQueue(int n) { //先判断队列是否满了 if(isFull()) { System.out.println("队列已满,请排队"); return; } //因为rear表示最后一个元素的后一个位置,肯定是空的,所以直接放进去即可不用加1 arr[rear] = n; //将rear后移,考虑环绕问题,所以用取模 的方式 rear = (rear+1)%maxSize; } //从队列中拿数据 public int getQueue() { //先判断队列是否为空 if(isEmpty()) { //抛异常不用return throw new RuntimeException("队列为空,暂无数值"); } //取队列中的第一值 int value=arr[front]; //此时要把front后移,保证再次取值拿到的是第一个值,同时考虑环绕问题 front = (front+1)%maxSize; return value; } //显示队列中的所有值 public void showQueue() { //先判断队列是否为空 if(isEmpty()) { throw new RuntimeException("队列为空,暂无数值"); } //遍历要从第一个数值front开始遍历 for(int i = front;i<size()+front;i++) { System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]); } } //求出当前列表数据的个数 public int size() { return (rear+maxSize-front)%maxSize; } //显示队列的头数据 public int headQueue() { if(isEmpty()) { throw new RuntimeException("队列为空,暂无数值"); } return arr[front]; } }
。。
原文地址:https://www.cnblogs.com/bai3535/p/12094059.html
时间: 2024-10-14 17:40:23