java数据结构循环队列的空满判断及长度计算

目录
  • 一、假溢出
  • 二、循环队列判断是空是满
  • 三、循环队列的长度计算
  • 四、代码实现

在上一章中,使用了数组模拟了队列。但是留下的问题是,把数据取完后,再往里加数据就不行了。

一、假溢出

这是因为数组的末尾已经被占用了,入队会继续在数组后面增加,于是产生数组越界。但是实际上,数组里是有空闲位置的,这种也可以叫“假溢出”。

为了解决“假溢出”的问题,于是乎有了循环队列。

既然数组后面满了,头部有空,那继续加进来的元素从头开始放即可。

接着上图,这时候有a6入队,于是rear的下标指向a6的下一个元素位置,看起来没什么问题。

但是继续有新的元素a7入队的时候,因为front一直没变,这时候rear指针跟front就重合了,也就是说此时front=rear

可是在上一章的代码里,我们是用front=rear来判断是否为空数组的。

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

现在是相等了,条件满足,但是数组是满的。

二、循环队列判断是空是满

这种情况看起来确实比较辣手,那如果不让这种情况出现不就可以了么?

假设,我们让数组始终保留一个元素空间,也就是让rear指向队列中最后一个元素的后一个位置。比如,当a6放入之后,此时就当做队列已经满了,这样的话就不会出现上述的情况了。

为了实现这种思路,front也需要做调整。在上一章中,front初始位置是指在了队头元素的前一个,现在我们让它就指在第一个元素。

队列的最大尺寸还是maxSize,那么,现在判断队列满的条件就可以是这样:

(rear+1)%maxSize = front

验证一下,下面的2种队列满情况:

左图:队列中,maxSize=5,front=0,rear=4,判断(4+1)% 5=0=front,队列已满

右图:队列中,maxSize=5,front=2,rear=1,判断(1+1)% 5=2=front,队列已满

继续验证一下,队列没满的情况:

队列中,maxSize=5,front=2,rear=0,判断(0+1)% 5=1≠front,队列未满

三、循环队列的长度计算

队列的长度,也就是说队列中实际存了多少个元素。

此时需要考虑rear与front之间的三种情况:

  • rear=front
  • rear>front
  • rear<front

第一种自然都清楚,队列为空。

第二种,rear>front,此时队列的长度为:rear-front

第三种,rear<front,比较复杂些。队列长度分为2段:一段是maxSize-front,另一段则是:0+rear(结合右图理解)。故此时队列总长度为两段相加:rear-front+maxSize

所以队列长度的通用计算公式为:

(rear-front+maxSize)% maxSize

四、代码实现

既然现在队列是满是空的判断条件有了,队列长度也能计算出来了,那么代码就好改造了(基于上一章),变成循环队列。

package circle;
import java.util.Scanner;
public class CircleArrayQueue {
    public static void main(String[] args) {
        System.out.println("-----测试循环队列-----");
        // 创建一个队列
        CircleArray circleArray = new CircleArray(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("g(get): 从队列取出数据");
            System.out.println("h(head): 显示队首的数据");
            key = scanner.next().charAt(0); // 接收一个字符
            switch (key) {
                case 's':
                    circleArray.showQueue();
                    break;
                case 'a':
                    System.out.println("请要添加的数");
                    int value = scanner.nextInt();
                    circleArray.addQueue(value);
                    break;
                case 'g':
                    try {
                        int res = circleArray.getQueue();
                        System.out.printf("取出的数据是:%d", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int headValue = circleArray.showHeadQueue();
                        System.out.printf("队首数据是:%d", headValue);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
            }
        }
        System.out.println("退出程序");
    }
}
class CircleArray {
    //表示数组最大容量
    private int maxSize;
    // 队列头,由之前调整为指向队列第一个元素
    private int front;
    // 队列尾,由之前调整为指向队列最后一个元素的后一个位置,为了空出一个元素位置
    private int rear;
    // 用于存放数据的数组
    private int[] arr;
    // 构造器
    public CircleArray(int arrMaxSize) {
        maxSize = arrMaxSize;
        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 num) {
        // 判断队列是否满了
        if (isFull()) {
            System.out.println("队列已满,不可加入数据");
            return;
        }
        arr[rear] = num;
        // 将rear后移,要考虑取模
        rear = (rear + 1) % maxSize;
    }
    // 拿出队列数据
    public int getQueue() {
        // 判断队列是否空
        if (isEmpty()) {
            // 抛出异常
            throw new RuntimeException("队列为空,不可取数据");
        }
        int tempValue = arr[front];
        front = (front + 1) % maxSize; //也要考虑取模,防止front不停的增加,导致越界
        return tempValue;
    }
    // 显示队列所有数据
    public void showQueue() {
        // 遍历
        if (isEmpty()) {
            System.out.println("队列为空");
            return;
        }
        // 从front开始遍历,遍历多少个实际存的元素即可
        for (int i = front; i < front + CircleQueueSize(); i++) {
            System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
        }
    }
    // 求出当前队列有效数据的个数
    public int CircleQueueSize() {
        return (rear - front + maxSize) % maxSize;
    }
    // 显示队里的队首数据
    public int showHeadQueue() {
        if (isEmpty()) {
            // 抛出异常
            throw new RuntimeException("队列为空,不可取数据");
        }
        return arr[front];
    }
}

重点的改动在于取模。

以上就是java数据结构循环队列的空满判断及长度计算的详细内容,更多关于java循环队列空满判断长度计算的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java代码实现循环队列的示例代码

    循环队列结构 队列特点 队列为一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有元素时,称为空队列. 队列的数据元素又称为队列元素.在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队.因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO-first i

  • java数据结构基础:顺序队列和循环队列

    目录 队列: 顺序队列: 代码实现: 循环队列: 代码实现: 总结 队列: 队列是一种受限制的线性表 只允许在表的一端进行插入,另一端进行删除 插入的一端称作队尾,删除的一端称作队头 具有先进先出的特性 顺序队列: 队列底层数据采用数组存储 设置队头指针front指向队头元素前一个位置,初始值为-1 设置队尾指针rear指向队尾元素,初始值为-1 判满:rear == maxSize - 1 判空:rear == front 代码实现: //顺序队列 public class ArrayQueu

  • Java循环队列原理与用法详解

    本文实例讲述了Java循环队列原理与用法.分享给大家供大家参考,具体如下: 在正式进行循环队列学习之前,我们先来看看在顺序队列中删除队首元素出现的问题 (1)设一个容量为capacity=8,size=5(a,b,c,d,e)的数组,左侧为队首.右侧为队尾. (2)出队一个元素后,需整体往前移动一位 #出队 #2整体前移一位 关于该种操作方式我们很容易得出时间复杂度为O(n). 这时我们就想可不可以在出队元素后,整体元素不往前移,而是在数组中记下队首front是谁,同时队尾tail指向在下一次元

  • Java动态循环队列是如何实现的

    一.队列 1.1 定义 队列 (Queue) 是一种限定性的有序线性表,它只允许在表的一端插入元素,而在另一端删除元素,所以队列具有先进先出 (Fist In Fist Out,缩写为FIFO)的特性. 在队列中,允许插入的一端叫做队尾(rear): 允许删除的一端则称为队头(front). 队列是一个有序列表,可以用数组或是链表来实现. 遵循先进先出的原则.即:先存入队列的数据,要先取出. 1.2 抽象数据类型 数据元素:可以是任意类型的数据,但必须属于同一个数据对象. 关系:队列中数据元素之

  • Java 1.8使用数组实现循环队列

    本文实例为大家分享了Java 1.8使用数组实现循环队列的具体代码,供大家参考,具体内容如下 1.引入 使用数组实现循环队列,功能如下: 1)isFull():队列满? 2)isEmpty():队列空? 3)add():添加元素. 4)pop():移除元素. 5)display():展示队列. 6)getSize():获取当前队列元素个数. 2.代码 package DataStructure; import java.util.Arrays; /** * @author: Inki * @em

  • java数据结构循环队列的空满判断及长度计算

    目录 一.假溢出 二.循环队列判断是空是满 三.循环队列的长度计算 四.代码实现 在上一章中,使用了数组模拟了队列.但是留下的问题是,把数据取完后,再往里加数据就不行了. 一.假溢出 这是因为数组的末尾已经被占用了,入队会继续在数组后面增加,于是产生数组越界.但是实际上,数组里是有空闲位置的,这种也可以叫“假溢出”. 为了解决“假溢出”的问题,于是乎有了循环队列. 既然数组后面满了,头部有空,那继续加进来的元素从头开始放即可. 接着上图,这时候有a6入队,于是rear的下标指向a6的下一个元素位

  • Java数据结构之队列(动力节点Java学院整理)

    队列的定义: 队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表. (1)允许删除的一端称为队头(Front). (2)允许插入的一端称为队尾(Rear). (3)当队列中没有元素时称为空队列. (4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表. 队列的修改是依先进先出的原则进行的.新来的成员总是加入队尾,每次离开的成员总是队列头上的(不允许中途离队). 队列的存储结构及实现 队列的顺序存储结构 (1) 顺序队列的定义: 队列

  • Java数据结构之队列的简单定义与使用方法

    本文实例讲述了Java数据结构之队列的简单定义与使用方法.分享给大家供大家参考,具体如下: 一.概述: 1.说明: 队列的原则时先进先出,就像生活中排队取票一样,谁排在前面谁先得到 2.有五个属性: 1)数组元素 2)最大空间 3)长度 4)队头 5)队尾 3.示例图: 二.代码实现 /** * @描述 对列 * @项目名称 Java_DataStruct * @包名 com.java.stack * @类名 Queue * @author chenlin * @version 1.0 * @S

  • Python 实现数据结构-循环队列的操作方法

    今天我们来到了循环队列这一节,之前的文章中,我介绍过了用python自带的列表来实现队列,这是最简单的实现方法. 但是,我们都知道,在列表中删除第一个元素和删除最后一个元素花费的时间代价是不一样的,删除列表的第一个元素,那么在它之后的所有元素都要进行移动.所以当列表特别长的时候,这个代价就比较明显了.我们本文介绍的循环队列可以避免这个问题,同样我们上篇文章提到的用链表实现的方法也可以避免. 下面,我们来介绍循环队列. 循坏队列 循环队列,就是将普通的队列首尾连接起来, 形成一个环状,并分别设置首

  • Java数据结构与算法之循环队列的实现

    目录 概述 循环队列 循环队列实现 改变队列大小 enqueue 方法 dequeue 方法 main 完整代码  概述 从今天开始, 小白我将带大家开启 Jave 数据结构 & 算法的新篇章. 循环队列 循环队列 (Circular Queue) 是一种特殊的队列. 循环队列解决了队列出队时需要将所有数据前移一位 (复杂度为 O(n)) 的问题. 循环队列的底层依然是数组, 不过增加了指向头和尾的指针. 循环队列实现 判断队列是否为空: 当头指针 Q.front == 尾指针 Q.rear,

  • 详解数据结构C语言实现之循环队列

    本文讲的是循环队列,首先我们必须明白下面几个问题 循环队列的基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置: (3)当队列为空时,front与rear的值相等,但不一定为零: 3.循环队列入队的伪算法 (1)把值存在rear所在的位置: (2)rear=(rear+1)%maxsize

  • 基于Java数组实现循环队列的两种方法小结

    用java实现循环队列的方法: 1.添加一个属性size用来记录眼下的元素个数. 目的是当head=rear的时候.通过size=0还是size=数组长度.来区分队列为空,或者队列已满. 2.数组中仅仅存储数组大小-1个元素,保证rear转一圈之后不会和head相等.也就是队列满的时候.rear+1=head,中间刚好空一个元素. 当rear=head的时候.一定是队列空了. 队列(Queue)两端同意操作的类型不一样: 能够进行删除的一端称为队头,这样的操作也叫出队dequeue: 能够进行插

  • java数组实现循环队列示例介绍

    从顶部进去数据,从底部出来数据,用数组实现队列,但是下面这个队列,只能进行一次存数值,取数值,不够完善. import java.util.Scanner; public class ArrayQueueDemo { public static void main(String[]args){ //定义队列大小maxsize ArrayQueue arrayQueue=new ArrayQueue(3); Scanner scanner=new Scanner(System.in); char

随机推荐