用java模拟环形队列的实现(java)

环形队列介绍:

  1. 队列是一个有序列表,可以用数组或者链表来实现;
  2. 遵循先入先出的原则,即:先存入队列的数据,先取出,后存入的后取出;即先进先出原则。
  3. 队列空间可以循环使用
  4. 示意图
    在这里插入图片描述

实现思路:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210331222345367.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2MzU2ODYx,size_16,color_FFFFFF,t_70
这里要解释一下取模运算,取模这个操作,比如a-b%c=d,可以理解为a和b之间的差值是n个c加上d,当数据是循环编号时,代表了a和b之间的绝对距离,这个距离的值为d。但是为什么我们求有效值不是用的(rear-front)%maxsize而是(rear+maxsize-front)%maxsize呢,因为在java中,%运算实际上是取余运算,计算的结果和设想的会有出入,可以看下百度百科的这个解释:
在这里插入图片描述
所以为了避免出错,我们把被除数a换算成非负数!
代码实现:

package com.xrw.queue;

import java.util.Scanner;

/**
 * @program: DataStructures
 * @description: 用数组实现环形队列:队列的特点:先进先出,后进后出;
 * 实现思路:1、定义属性,队列的大小maxSize,队列的头部front指向队列的第一个元素,队列的尾部rear指向队列的最后一个元素的后一个节点,默认队列空出来一个节点
 * 2、front = 0 ,rear = 0;
 * 3、插入一个值:front不变,插入数据,rear = (rear+1)%maxSize;直到队列满:(rear+1-front)%maxsize == 0,就不允许插入
 * 4、取出一个值:front = (front+1)%maxSize,取出数据;直到队列为空:rear == front,就不允许取出
 * 5、队列的有效值的个数为 (rear+maxsize-front)%maxsize
 * @author: 谢荣旺 1429382875@qq.com
 * @create: 2021-04-01 22:23
 **/
public class CircleArrayQueueDemo {

    public static void main(String[] args) {
        //新建一个队列
        CircleArrayQueue arrayQueue = new CircleArrayQueue(4);
        //接收用户输入
        char key = ' ';
        //输入流
        Scanner scanner = 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("p(pop): 从队列取出数据");
            System.out.println("h(head): 查看队列头的数据");
            key = scanner.next().charAt(0);//获取用户输入的第一个字符
            switch (key){
                case 's':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("输入一个数");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;
                case 'p':
                    try {
                        int i = arrayQueue.popQueue();
                        System.out.printf("取出的数据是%d\n",i);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int i = arrayQueue.getHead();
                        System.out.printf("队列的头数据为%d\n",i);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    loop = false;
                    break;
                default:
                    System.out.println("输入非法,请重新输入");
                    break;
            }
        }
        System.out.println("程序退出~~");
    }
}

/**
 * @Description: 环形队列
 * @Author: 谢荣旺
 * @Date: 2021/4/1
 */
class CircleArrayQueue{
    //队列最大容量
    private int maxSize;
    //队列第一个元素的位置
    private int front;
    //队列最后一个元素的后一个位置
    private int rear;
    //实际存储数据的数组
    private int[] arr;

    /**
     * @Description: 构造函数
     * @param maxSize: 最大容量
     * @return:
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public CircleArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        front = 0;
        rear = 0;
        arr = new int[maxSize];
    }

    /**
     * @Description: 判断队列是否已满
     * @param :
     * @return: boolean
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public boolean isFull(){
        return (rear+1-front)%maxSize == 0;
    }

    /**
     * @Description: 判断队列是否为空
     * @param :
     * @return: boolean
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public boolean isNull(){
        return rear == front;
    }

    /**
     * @Description: 往队列里面添加数组
     * @param n: 要插入的数据
     * @return: void
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public void addQueue(int n){
        if (isFull()){
            System.out.println("队列已满,无法插入");
            return;
        }
        arr[rear] = n;
        rear = (rear+1)%maxSize;
    }

    /**
     * @Description: 从队列中取出一个数据
     * @param :
     * @return: int
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public int popQueue(){
        if (isNull()){
            //队列为空就抛出异常
            throw new RuntimeException("队列为空,没有数据");
        }
        int pop = arr[front];
        front = (front+1)%maxSize;
        return pop;
    }

    /**
     * @Description: 显示队列
     * @param :
     * @return: void
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public void showQueue(){
        if (isNull()){
            System.out.println("队列为空,没有数据");
            return;
        }
        //先赋值是因为java的for循环对于函数条件,每次都会重新计算值,提前赋值可以提高运算效率
        int size = size();
        for (int i = front;i<front+size;i++){
            System.out.printf("arr[%d] = %d\n",i%maxSize,arr[i%maxSize]);
        }
    }

    /**
     * @Description: 获取队列的第一个数据,但是不删除该数据
     * @param :
     * @return: int
     * @Author: 谢荣旺
     * @Date: 2021/3/31
     */
    public int getHead(){
        if (isNull()){
            throw new RuntimeException("队列为空,没有数据");
        }
        return arr[front];
    }

    /**
     * @Description: 判断队列有效数据的个数
     * @param : 
     * @return: int
     * @Author: 谢荣旺
     * @Date: 2021/4/1
     */
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }
}

效果:

D:\code\java\jdk1.8.0_181\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:56152,suspend=y,server=n -javaagent:C:\Users\A\.IntelliJIdea2019.3\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\code\java\jdk1.8.0_181\jre\lib\charsets.jar;D:\code\java\jdk1.8.0_181\jre\lib\deploy.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\localedata.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\sunec.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;D:\code\java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;D:\code\java\jdk1.8.0_181\jre\lib\javaws.jar;D:\code\java\jdk1.8.0_181\jre\lib\jce.jar;D:\code\java\jdk1.8.0_181\jre\lib\jfr.jar;D:\code\java\jdk1.8.0_181\jre\lib\jfxswt.jar;D:\code\java\jdk1.8.0_181\jre\lib\jsse.jar;D:\code\java\jdk1.8.0_181\jre\lib\management-agent.jar;D:\code\java\jdk1.8.0_181\jre\lib\plugin.jar;D:\code\java\jdk1.8.0_181\jre\lib\resources.jar;D:\code\java\jdk1.8.0_181\jre\lib\rt.jar;E:\我的文件\学习\数据结构与算法\源代码\DataStructures\out\production\DataStructures;D:\code\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar" com.xrw.queue.CircleArrayQueueDemo
Connected to the target VM, address: '127.0.0.1:56152', transport: 'socket'
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
a
输入一个数
1
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
a
输入一个数
2
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
a
输入一个数
3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
s
arr[0] = 1
arr[1] = 2
arr[2] = 3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
a
输入一个数
1
队列已满,无法插入
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
p
取出的数据是1
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
a
输入一个数
4
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
s
arr[1] = 2
arr[2] = 3
arr[3] = 4
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
p
取出的数据是2
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
a
输入一个数
7
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
s
arr[2] = 3
arr[3] = 4
arr[0] = 7
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
h
队列的头数据为3
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
s
arr[2] = 3
arr[3] = 4
arr[0] = 7
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
p(pop): 从队列取出数据
h(head): 查看队列头的数据
e
程序退出~~
Disconnected from the target VM, address: '127.0.0.1:56152', transport: 'socket'

Process finished with exit code 0

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
做一门精致,全面详细的 java数据结构算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值