Bootstrap

(3)数组模拟环形队列

数组模拟环形队列

对前面的数组模拟队列的优化,充分利用数组. 因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:

  1. 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front

假设maxsize=4 那实际只能放3个值 arr[0], arr[1], arr[2],当添加到 arr[rear] arr[2] (rear+1)%4 =3 在添加下一次值的时候 (3+1)%4=0=front 此时队列满了,存了3个数。
当有一个数出队列,(front+1)%4=1 front变为1.
此时添加数据 ,判断满 rear还是等于 (3+1)%4不等于front arr[3] 下一位又是0
rear
2) rear == front [空]
3) 分析示意图
在这里插入图片描述
代码实现

import java.util.Scanner;

public class CircleDemo {
    public static void main(String[] args) {
        CircleQueue queue=new CircleQueue(3);  //中间有预留空位,实际容量为2
        char key=' '; //接受的用户指令
        Scanner sc=new Scanner(System.in);
        boolean loop=true;
        while(loop) {
            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): 查看队列头的数据");
            key = sc.next().charAt(0);//接收一个字符

            switch (key) {
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("输出一个数");
                    int value = sc.nextInt();
                    queue.addQueue(value);
                    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.peek();
                        System.out.printf("队列头的数据是%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e': //退出
                    sc.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出~~");
    }
    }


class CircleQueue{
    private int maxSize; //数组的最大容量
    private int front; //队头
    private int rear; //队尾
    private int[] arr; //存放数据的数组,模拟队列

    //创建队列的构造方法 给定队列大小
    public CircleQueue(int maxSize){
        this.maxSize=maxSize;
        arr=new int[maxSize];
        front=0;
        rear=0;
    }

    //判断队列是否已满
    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+1)%maxSize;  //是环 跳到最前面空的
    }

    //出队列
    public int getQueue(){
        //先判断队列是否为空
        if(isEmpty()){
            throw new RuntimeException("队列为空");//抛出运行时异常 队列为空
        }
        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(){
        return (rear-front+maxSize)%maxSize;
    }



    //显示队列头 ,注意不是取出头
    public int peek(){
        if(isEmpty()){
            throw new RuntimeException("对列为空");
        }
        return arr[front];
    }
}

测试
注意看每次的队列的索引
队列是有个空位 ,让队列可以一直循环

0,1,2
取掉第一个
1,2,3
取掉前两个
3 ,0,1

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:D:\idea\IntelliJ IDEA 2022.1\lib\idea_rt.jar=50042:D:\idea\IntelliJ IDEA 2022.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_221\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar;D:\idea-workspace\20220508\out\production\20220508" CircleDemo
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
1
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
2
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
s
arr[0]=1
arr[1]=2
arr[2]=3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
g
取出的数据是1
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
4
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
s
arr[1]=2
arr[2]=3
arr[3]=4
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
g
取出的数据是2
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
g
取出的数据是3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
5
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
a
输出一个数
6
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据
s
arr[3]=4
arr[0]=5
arr[1]=6
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 查看队列头的数据


;