java中用数组实现环形队列的示例代码

本篇文章主要讲述了使用数组实现环形队列的思路以及具体代码

一、队列是什么

我们先来看下百科的解释:
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头
总结起来两点:
1.一种线性表
2.添加操作只能在表尾,删除操作在表头(先进先出)

二、实现队列的思路

1.初始化一个空队列

初始化一个大小固定的数组,并将头指针,尾指针都指向下表为0的位置,但其实这种初始化头指针指向的是队首,尾指针指向的是队尾的后一个元素。

2.往队列里添加元素

往队列里添加元素,尾指针后移一位。

一直添加直到队列满

这个时候尾指针已经出现在数组下标外了

3.消费队列元素

每消费一个队列元素,头指针指向的元素出队,并且后移一位

再消费两个

这个时候我们想往队列里继续添加元素,尾指针后移,然后发现出现了假溢出的情况,因为尾指针无法再向后移动,而队列实际上并没有满,我们又无法继续往队列里添加数据。这个时候其实有两种解决方案。
方案一:我们每消费一个元素,其后面的元素都整体往前移动一位,就像我们生活中排队打饭一样,后面的人都往前挪一挪。但这种方案带来的后果是,带来的时间开销太大,因为基本上要操作所有的元素,所以这种方案不可行。
方案二:尾指针在指向下表为最后一个元素时,再添加元素,如果还有空位,就将尾指针重新指向0,头指针在取到下表数组末尾时,如果前面还有元素,头指针也指向0,这就是我们说的环形队列。

三、实现环形队列

1.环形队列示例图

尾指针重新指向零

再添加一个元素

连续消费三个元素,如果前面还有元素,头指针也指向0

这个时候我们发现那个原来熟悉的队列又回来了。

2.代码实现

/**
 * description:数组实现环形队列
 * author: xiaowang
 * */
public class MyQueue<E> {
    // 队列最大个数
    private int size;
    // 元素真实个数
    private int number;
    // 头指针,指向队列的第一个元素即队头
    private int front;
    // 尾指针,指向队尾的后一个元素(非队尾)
    private int rear;
    // 队列具体值
    private Object[] values;
    // 队列满标记,当队列是满的时候为true
    private boolean isFullFlag;

    /**构造器*/
    public MyQueue(int size){
        if (size<0){
            throw new RuntimeException("初始化队列时,队列最大元素个数不能为负");
        }
        this.front  = 0;
        this.rear = 0;
        this.number = 0;
        this.isFullFlag = false;
        this.size = size;
        this.values = new Object[size];

    }

    /**往队列里添加元素 添加成功返回true 失败返回false*/
    public boolean addToQueue(E e){
        // 判断队列是否已经满了
        if (isFullFlag){
            System.out.println("队列已满,无法继续添加元素");
            return false;
        }
        // 添加元素
        values[rear] = e;
        // 元素个数加一
        number++;
        // 尾指针后移一位,若已经指向数组最后的下表,则重新指向0
        if (rear == size-1){
            rear = 0;
        }else{
            rear++;
        }
        // 添加完这个元素,判断队列是否已经满了,若满则标记为true
        if (rear==front){
            isFullFlag = true;
        }
        return true;
    }
    /**从队列里取出数据,队头数据*/
    public E getFromQueue(){
        // 判断队列是否为空
        if (number==0||size==0){
            System.out.println("队列为空,无法从队列中获取数据");
            return null;
        }
        // 临时变量
        E e = (E) values[front];
        // 队头置空
        values[front] = null;
        // 个数减一
        number--;
        // 头指针后移,若已经指向数组最后的下表,则重新指向0
        if (front==size-1){
            front = 0;
        }else {
            front++;
        }
        // 取队列之前若是满的状态,则更新状态
        if (isFullFlag){
            isFullFlag = false;
        }
        return e;
    }
    /**获取目前有几个元素正在进行排队*/
    public int getNumber(){
        return number;
    }
    /**获取队列的最大个数*/
    public int getSize(){
        return size;
    }
    /**查看队列在数组里保存的详细情况*/
    public String toString(){
        StringBuffer valueStr = new StringBuffer();
        valueStr.append("[");
        for (int i = 0; i < size; i++) {
            if (i!=size-1){
                valueStr.append(values[i]+",");
            }else{
                valueStr.append(values[i]+"]");
            }
        }
        return valueStr.toString();
    }
}

测试代码

public class TestQueue {

    public static void main(String[] args) {
        MyQueue<String> queue = new MyQueue<String>(5);
        Scanner scanner = new Scanner(System.in);
        Scanner scanner2 = new Scanner(System.in);
        boolean isCan = true;
        while (isCan){
            System.out.println("欢迎来到小王排队系统,您可以使用以下功能。\n添加:1;取出:2;展示:3;获取排队个数:4;退出:0。");
            int flag = scanner.nextInt();
            switch (flag){
                case 1 :
                    System.out.println("请输入一个数据:");
                    String data = scanner2.nextLine();
                    boolean isSuccess = queue.addToQueue(data);
                    if (isSuccess){
                        System.out.println("添加成功~~~");
                    }
                    break;
                case 2 :
                    String dataFromQueue = queue.getFromQueue();
                    if (dataFromQueue!=null){
                        System.out.println("本次取出的数据为:"+dataFromQueue);
                    }
                    break;
                case 3 :
                    System.out.println("队列详情为:\n"+queue.toString());
                    break;
                case 4 :
                    System.out.println("目前有"+queue.getNumber()+"个元素正在进行排队");
                    break;
                default:
                    isCan = false;
                    System.out.println("已退出...");
                    break;
            }
        }

    }
}

总结

到此这篇关于java中用数组实现环形队列的示例代码的文章就介绍到这了,更多相关java 数组环形队列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java循环调用多个timer实现定时任务

    通常在使用java实现定时任务时,有两种方法,一种是spring中的schedule(cron = " */5 * * * ?"),另一种就是java中的timer, timer+TimerTask配合实现,这里附上Timer对象的一些常用api Timer() 创建-个新计时器. Timer(boolean isDaemon) 创建一个新计时器, 可以指定其相关的线程作为守护程序运行. Timer(String, name) 创建一个新计时器,其相关的线程具有指定的名称. Timer

  • java 定义长度为0的数组/空数组案例

    如下: int[] array = new int[0]; // 定义一个长度为 0 的数组 / 空数组 Sring[] arr = new String[0]; // 定义一个长度为 0 的数组 / 空数组 长度为 0 的数组 / 空数组 并不是 null 有时数组里可能只有一个空字符串 "",这时数组长度是 1.这种情况也要注意判断. if ( arr.length == 1 && arr[ 0 ].equals( "" ) ) { System

  • java二维数组指定不同长度实例方法

    我们知道二维数组,是在一维数组的基础上进行了维度的增加.那么在实际使用的过程中,有时候我们所需要的二维数组,它们其中的维度是不同的,这就需要我们手动的进行设置.下面我们就来一起探究,二维数组在改变维度长度大小的方法,并辅以实例进行代码展示. 1.二维数组的每个元素都是一个一维数组,这些数组不一定都是等长的.声明二维数组的时候可以只指定第一维大小,空缺出第二维大小,之后再指定不同长度的数组.但是注意,第一维大小不能空缺(不能只指定列数不指定行数). public class ArrayTest4

  • Java 自定义动态数组方式

    Java自定义动态数组 1.静态数组向动态数组转变 (1)静态数组,数组空间固定长度 这个数组空间总长为4,如果此时新插入一个数据就会报数组空间不足 (2)静态数组如何转变成动态数组 第一步:创建一个空间是data数组两倍的newData数组(扩容): 第二步:把data数组中的元素全部赋值到newData数组: 2.数组扩容程序 // 数组扩容 private void resize(int newCapacity){ E[] newData = (E[]) new Object[newCap

  • java循环练习的简单代码实例

    ★打印九九乘法表 复制代码 代码如下: public class TestDemo {     public static void main(String[] args){         for(int b=1;b<10;b++){             for(int a=1;a<=b;a++)                 System.out.print(a+"*"+b+"="+a*b+"\t");           

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

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

  • Java基础之数组详解

    前言 我们了解数组这个概念之前,我们先思考下面几个问题. 如果我们需要两个数据,那么直接创建两个变量即可 int a; int b; 如果需要五个数据,那么可以创建五个变量 int a; int b; int c; int d; int f; 但如果我们需要100个甚至是1万个数据,那么我们创一万个变量?显然这是不现实的.这个时候就需要我们的数组来起作用!帮我们"批量"创建变量. 由上可以得出:数组的本质就是让我们能"批量"创建相同类型的变量! 一.数组的概念 数组

  • Java基础之数组模拟循环队列

    一.队列简介 队列是一个有序列表,遵循"先入先出"的原则,即先存入队列的数据要先取出,后存入的数据后取出. 队列有两种存储表示,顺序表示和链式表示.顺序表示可以用数组来实现. 二.数组模拟队列 用数组模拟队列时,设两个值front=0,rear=0.front表示队列首部第一个数据所在位置,rear表示尾部最后一个数据的下一个位置. 将数据插入数组队列时(入队),从尾部进行插入,即array[rear] = value,同时rear后移,rear++.取出数据时(出队),从头部取出数据

  • 使用java一维数组模拟压栈弹栈

    思路 先进后出,优先解决压栈的问题,之后解决弹栈和main方法 功能 随时模拟压栈 随时模拟弹栈 防止异常和各种错误 随时可以遍历"栈"中存在的变量的方法,压栈弹栈栈帧清晰可见! 使用演示: 压栈: 栈满检测: 遍历栈内存和栈帧: 只要栈中有变量就会输出栈帧: 弹栈: 栈空检测:(没有变量,栈帧不输出!) 源码: import java.util.Scanner; public class MoveTest01 { //局部变量供栈方法的遍历数组使用 static int i; //创

  • 几道java循环练习题(适合新人)

    1.求水仙花数 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数, 其各位数字立方和等于该数本身. 例如:153是一个"水仙花数", 因为153=1的三次方+5的三次方+3的三次方. //第一题,水仙花数 public class demo4 { public static void main(String[] args) { System.out.println("1000以内的数字"); int u=0; for(

随机推荐