剑指offer——循环队列

        针对剑指offer——队列_super 琪的博客-CSDN博客该篇文章提出的问题,我利用循环队列解决了上述存在的问题,并对之前的队列初始化进行了部分修改,将两个辅助指针的初始值给改变了,两者的含义也随之发生了变化,front和rear的初始值都修改成了0,front的含义变成了一直代表队列的第一个数据的下标,rear的含义变成了代表队列最后一个数据后一个数据的下标,因此在队列的maxSize的情况下,队列只能存放maxSize - 1个数据,因为留有一个空白数组下标作为rear,这样便于我们理解(也可以不留该空白空间)。

        将队列的初始化的构造器改造成以下的代码:

class CircleQueue {
    //队列的最大容量
    private int maxSize;
    //队列的第一个数据
    private int front;
    //队列的最后一个数据的后面一个区间
    private int reat;
    //队列的主体数组
    private int[] arrays;

    public CircleQueue(int maxSize) {
        this.maxSize = maxSize;
        //初始化队列容量
        arrays = new int[maxSize];
    }
}
构造器中没有对front和rear进行赋值,因为int的默认值为0

        判断队列为空和队列已满的条件也随之改变,因为变成了循环队列,所以判断队列满需要进行取模运算,条件为 (reat + 1) % maxSize == front, 因为约定留有一个空白容量,所以rear + 1能够对maxSize取模等于front时,就代表队列已满;判断队列为空的条件变成了rear == front。代码如下:

    //判断队列是否为空
    public boolean isEmpty() {
        return reat == front;
    }

    //判断队列是否已满
    public boolean isFull() {
        return (reat + 1) % maxSize == front;
    }

         添加数据总体来说是相差不大,但是rear的值变成了(rear + 1) % maxSize去得到,因为为了防止rear超出maxSize - 1,所以需要对其进行取模运算,代码如下:

    //往队列里面添加数据
    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("队列已满,无法新增新的数据!");
            return;
        }
        arrays[reat] = n;
        reat = (reat + 1) % maxSize;
    }

        获取队列数据也同添加数据一个原因,front 的赋值变成了( front + 1) % maxSize,代码如下:

    //从队列之中获取数据
    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,请添加数据!");
        }
        int value = arrays[front];
        front = (front + 1) % maxSize;
        return value;
    }

        遍历队列数据的方法内部逻辑也发生了一些改变,因为队列数组中的数据不一定都是从0下标开始存储的,因为增加数据的时候采用了取模的运算,所以遍历的时候改用了i % maxSize的下标遍历队列,代码如下:

    //遍历队列数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空,请添加数据!");
            return;
        }
        System.out.println("队列数据为:");
        for (int i = front; i < front + size(); i++) {
            System.out.printf("arrays[%d]=%d\n", i % maxSize, arrays[i % maxSize]);
        }
    }

        相比较之前数组模拟的队列,循环队列我新增了一个方法,就是获取有效数据的个数的size()方法,这个方法能够让我们快速知道队列中有几个有效数据,代码如下:

    //求出当前队列的有效数据
    public int size() {
        return (reat + maxSize - front) % maxSize;
    }

        显示头部数据代码没有太大的变化,直接返回arrays[front]即可,代码如下:

    //显示头部数据
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,请添加数据!");
        }
        return arrays[front];
    }

       下述是整个循环队列的代码以及测试代码

import java.util.Scanner;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {
        CircleQueue circleQueue = new CircleQueue(3);
        char key = ' ';
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        while (loop) {
            System.out.println("s(showQueue): 显示队列");
            System.out.println("e(exit): 退出程序");
            System.out.println("a(addQueue): 添加队列数据");
            System.out.println("g(getQueue): 获取队列数据");
            System.out.println("h(headQueue): 获取队列头部数据");
            key = scanner.next().charAt(0);
            switch (key) {
                case 's':
                    circleQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("输入一个数");
                    int value = scanner.nextInt();
                    circleQueue.addQueue(value);
                    break;
                case 'g':
                    try {
                        System.out.printf("取出的数据是%d\n", circleQueue.getQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        System.out.printf("队列头部数据为%d\n", circleQueue.headQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序结束!");
    }
}

class CircleQueue {
    //队列的最大容量
    private int maxSize;
    //队列的第一个数据
    private int front;
    //队列的最后一个数据的后面一个区间
    private int reat;
    //队列的主体数组
    private int[] arrays;

    public CircleQueue(int maxSize) {
        this.maxSize = maxSize;
        //初始化队列容量
        arrays = new int[maxSize];
    }

    //判断队列是否为空
    public boolean isEmpty() {
        return reat == front;
    }

    //判断队列是否已满
    public boolean isFull() {
        return (reat + 1) % maxSize == front;
    }

    //往队列里面添加数据
    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("队列已满,无法新增新的数据!");
            return;
        }
        arrays[reat] = n;
        reat = (reat + 1) % maxSize;
    }

    //从队列之中获取数据
    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,请添加数据!");
        }
        int value = arrays[front];
        front = (front + 1) % maxSize;
        return value;
    }

    //遍历队列数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空,请添加数据!");
            return;
        }
        System.out.println("队列数据为:");
        for (int i = front; i < front + size(); i++) {
            System.out.printf("arrays[%d]=%d\n", i % maxSize, arrays[i % maxSize]);
        }
    }

    //求出当前队列的有效数据
    public int size() {
        return (reat + maxSize - front) % maxSize;
    }

    //显示头部数据
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,请添加数据!");
        }
        return arrays[front];
    }
}

        此上所述是我完善了之前的数据模拟队列的bug解决方案以及代码实现,有错误烦请大佬指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

super 琪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值