zoukankan      html  css  js  c++  java
  • 3、队列-数组模拟环形队列

    来源:https://www.bilibili.com/video/BV1B4411H76f?p=15

    一、思路

    1、环形队列的属性依然包括:队列的最大容量(maxSize),队列头指针(front),队列尾指针(rear),以及用来存放数据的数组(arr);

    2、需要注意的是,在此不能通过【指针++】的形式给下标赋值,这里用取模的方式实现下标的计算;

    3、通过取模的形式,那么头指针和尾指针的初始值不应该被定义为-1,这里两者的初始值为0;

    4、这里同样需要判断队列为空还是队列满,如果在当前状态下,头指针和尾指针重叠不好判断到底是空还是满,因此给队列加了一个【约定位置】。假设队列的大小想设置为3,那么加入【约定位置】之后,用来模拟队列的数组arr的大小应该是4。在不取出数据的情况下,front=0,当添加完第3个数据时,尾指针所在的位置是下标3,其下一个位置就是下标0(环形),由此可以判断队列满;同理,添加完3个数据后,想要取出,依次取出3个数据后,头指针所在的位置是下标3,两者重叠,由此判断队列空。这样就可以区分开了。

    二、实现

    1、创建一个代表队列的类,并将队列头指针和尾指针初始化为0。用来模拟队列的数组arr的大小为队列的大小+1。此处默认要添加的数据为int类型

     1 public class CircleArrayQueue {
     2     private int maxSize;//队列大小
     3     private int front;//头指针
     4     private int rear;//尾指针
     5     private int[] arr;//模拟队列的数组
     6 
     7     //构造器 环形不能像以前一样 【尾指针++】 【头指针++】 通过取模的方式给两个指针赋值
     8     //不能再用-1这个初值,于是给maxSize多加了一个【约定位置】,代替之前的-1位置。多出的不用于存值
     9     public CircleArrayQueue(int maxSize) {
    10         this.maxSize = maxSize + 1;//多出一个作为约定
    11         this.front = 0;//便于取模
    12         this.rear = 0;//便于取模
    13         this.arr = new int[this.maxSize];
    14     }
    15 }

    2、在CircleArrayQueue类中增加一个向队列中添加数据的方法。由于只有队列不满时才可以添加,因此还要额外添加一个判断队列满的函数。

     1     //判断队列满 尾指针处于【约定位置】时,下个是头指针,则满
     2     public boolean isFull(){
     3         return (rear+1) % maxSize == front;
     4     }
     5     //添加数据
     6     // 原:添加时rear++,加入数据
     7     // 现:rear初始为0 添加数据后的新位置为(rear+1)% maxSize
     8     //添加完最后一个,指针会指向【约定位置】 若中间没有取值,该【约定位置】的下一个位置对应的就是头指针的位置。下次添加就会判断为队列满
     9     public void addData(int data){
    10         if(this.isFull()){
    11             System.out.println("队列已满,不能继续添加数据");
    12         }else {
    13             arr[rear] = data;
    14             rear =(rear+1) % maxSize;
    15         }
    16     }

    3、在CircleArrayQueue类中增加一个展示队列数据的方法,测试一下增加数据的功能。由于只有当队列不为空时才能对数据进行展示,因此需要再添加一个判断队列空的方法。此外,展示数据这里用的是for循环,因此还添加了一个计算当前队列的有效数据个数的方法。

     1     //判断队列空 尾指针处于【约定位置】时 头指针也处于【约定位置】 则空
     2     public boolean isEmpty(){
     3         return rear == front;
     4     }
     5 
     6     //计算队列的有效数据个数
     7     public int dataCount(){
     8         return (rear + maxSize - front) % maxSize;
     9     }
    10     public void showData(){
    11         if(isEmpty()){
    12             System.out.println("队列为空,不能展示数据");
    13         }else {
    14             for (int i = front; i < front+dataCount();i++){
    15                 System.out.printf("arr[%d]=%d  ",i % maxSize,arr[i % maxSize]);
    16             }
    17         }
    18     }    

    对增加数据的功能进行测试

     1     public static void main(String[] args) {
     2         int maxSize = 3;
     3         CircleArrayQueue circleArrayQueue = new CircleArrayQueue(maxSize);
     4 
     5         Scanner sc = new Scanner(System.in);
     6         circleArrayQueue.showData();
     7 
     8         while (true){
     9             int value = sc.nextInt();
    10             circleArrayQueue.addData(value);
    11             circleArrayQueue.showData();
    12         }
    13     }

    结果

    队列为空,不能展示数据
    1
    arr[0]=1  
    2
    arr[0]=1  arr[1]=2  
    3
    arr[0]=1  arr[1]=2  arr[2]=3  
    4
    队列已满,不能继续添加数据
    arr[0]=1  arr[1]=2  arr[2]=3 

    4、在CircleArrayQueue类中增加一个出队列功能。同时展示当前的头指针。

     1     public int removeData(){
     2         if(isEmpty()){
     3             throw new RuntimeException("队列为空,无法移除数据");
     4         }else{
     5             int val = arr[front];
     6             front = (front + 1) % maxSize;
     7             return val;
     8         }
     9     }
    10 
    11     //输出头指针对应的内容
    12     public int headPoint(){
    13         if(this.isEmpty()){
    14             throw new RuntimeException("队列为空,无法寻找头指针");
    15         }else {
    16             return arr[front];
    17         }
    18     }

    测试

     1     public static void main(String[] args) {
     2         int maxSize = 3;
     3         CircleArrayQueue circleArrayQueue = new CircleArrayQueue(maxSize);
     4         circleArrayQueue.addData(1);
     5         circleArrayQueue.addData(2);
     6         circleArrayQueue.addData(3);
     7 
     8         int val = 0;
     9 
    10         val = circleArrayQueue.removeData();
    11         System.out.println("移除的值为:"+val);
    12         System.out.println("头指针对应的值为:"+ circleArrayQueue.headPoint());
    13         circleArrayQueue.showData();
    14         System.out.println();
    15 
    16         System.out.println("添加一个数据");
    17 
    18         circleArrayQueue.addData(4);
    19 
    20         circleArrayQueue.showData();
    21 
    22         System.out.println();
    23 
    24         val = circleArrayQueue.removeData();
    25         System.out.println("移除的值为:"+val);
    26         System.out.println("头指针对应的值为:"+ circleArrayQueue.headPoint());
    27         circleArrayQueue.showData();
    28 
    29         System.out.println();
    30 
    31         val = circleArrayQueue.removeData();
    32         System.out.println("移除的值为:"+val);
    33         System.out.println("头指针对应的值为:"+ circleArrayQueue.headPoint());
    34         circleArrayQueue.showData();
    35 
    36         System.out.println();
    37 
    38         val = circleArrayQueue.removeData();
    39         System.out.println("移除的值为:"+val);
    40         System.out.println("头指针对应的值为:"+ circleArrayQueue.headPoint());
    41         circleArrayQueue.showData();
    42 
    43         System.out.println();
    44 
    45         val = circleArrayQueue.removeData();
    46         System.out.println("移除的值为:"+val);
    47         System.out.println("头指针对应的值为:"+ circleArrayQueue.headPoint());
    48         circleArrayQueue.showData();
    49     }

    结果

    移除的值为:1
    头指针对应的值为:2
    arr[1]=2  arr[2]=3  
    添加一个数据
    arr[1]=2  arr[2]=3  arr[3]=4  
    移除的值为:2
    头指针对应的值为:3
    arr[2]=3  arr[3]=4  
    移除的值为:3
    头指针对应的值为:4
    arr[3]=4  
    移除的值为:4
    Exception in thread "main" java.lang.RuntimeException: 队列为空,无法寻找头指针
        at com.neuzhaoxin.queue.CircleArrayQueue.headPoint(CircleArrayQueue.java:69)
        at com.neuzhaoxin.queue.CircleArrayQueueTest.main(CircleArrayQueueTest.java:59)

    需要注意的是,所谓的【约定位置】对于数组来说是在不断变化的。不要通过数组下标来看这个环形队列,要通过头指针看其具体变化。

  • 相关阅读:
    关于vue2.x使用axios以及http-proxy-middleware代理处理跨域的问题
    vue-resource的使用
    从头开始开发一个vue幻灯片组件
    图与例解读Async/Await
    浅谈web缓存
    APICloud框架——总结一下最近开发APP遇到的一些问题 (三)
    编写现代 CSS 代码的 20 个建议
    仿微信联系人列表滑动字母索引
    初来乍到,向各位大牛虚心学习
    转发80端口的脚本
  • 原文地址:https://www.cnblogs.com/zhao-xin/p/13108576.html
Copyright © 2011-2022 走看看