Java数组模拟队列

Java数组模拟队列

简介

本文主要内容在Java代码中用数组模拟一个队列出来,这里只简要一提,不过多的介绍队列基本概念

队列是一种特殊的线性表,特点是先进先出。

和栈相似,它们的操作都是受限的。

这里要说的队列,只有两种操作,插入一个数据称为入队,删除一个数据称为出队,并且只能从队尾插入数据,只能在队头删除数据。

队列的数组实现

从百度百科中可以看到对队列的描述

简要来说,实现一个队列,本质上需要一片连续的存储空间,可以是静态分配,也可以动态申请

数组呢,正好就可以贴合这个要求,静态分配一段定长的连续内存空间

除此之外,还需要两个指针,一个指向队头,一个指向队尾

入队操作是在队尾添加数据,所以要在指向队尾的指针后一个位置添加数据,并且将指针指向新的队尾,也就是尾指针后移

出队操作是取出并删除队头的数据,其实删除数据的操作,就是在指向队头的指针处取得数据返回,然后将队头指针后移即可

我们发现,在操作数据的同时,需要伴随着指针的移动

分析一把,如果将头指针正好指向当前队头,尾指针正好指向当前队尾

注意:完整实现一个队列,需要有入队、出队、初始化三个操作。但用数组实现队列,因为存储空间是静态分配的定长空间,意味着队列容量有最大值,所以还需要判断队列满和队列空两种情况

1.入队:将尾指针后移一下,然后,将数据放到尾指针位置;(需要先判断队列是否还没满)

2.出队:将头指针位置的数据取出,然后,后移头指针;(需要先判断是否有数据可以出队)

3.判断队列的空满问题:

这种方式下,在操作出入队之前,尾指针正好指向队尾,头指针正好指向队头

所以,尾指针数值 - 头指针数值 +1 = 当前队列数据量,我们判断这个计算出的当前队列数据量,如果等于最大容量就说明队列满了,如果等于0就说明队列是空的

4.初始化队列:

初始化队列时,首先分析初始化的队列是空的,根据判断队列为空的方式,发现,当队列空时,头指针在尾指针的后一个位置;再分析第一个入队的数据要放在数组的第一个位置,也就是索引0的位置,而入队时先将尾指针后移,再将数据放在尾指针位置,所以初始化尾指针要指向-1;而头指针要在尾指针后一位,也就是初始化头指针指向0。

5.改进:

这样的方式实现队列后,会发现指针一直在后移,添加到最大容量后,指针就会超出边界,即便数据都已经出列了,也无法再入队,所以其实当指针移动到最大容量位置时,再向后移应该是移动到第一个,让队列首尾相连变成一个环状

实现这个的方式是,每次在移动指针后进行一次(指针%最大容量)的取余运算

但这样会出现问题,原先的计算当前数据量公式就不再正确,还需要将(结果%最大容量)进行取余运算

也可以放任指针持续后移,在取数据和插入数据的时候对指针取余,这样不影响计算数据量公式

实现方式其实并不唯一,取决于你对头尾指针的设定

下面的代码演示中,设定为:头指针指向队列头的前一个数据,尾指针指向队列尾

区别就是:

1.判断队列容量:尾指针-头指针正好等于队列容量,不需要加一

2.入队出队操作都是先移动指针,再操作数据

眼观千遍,不如手动一遍

读者朋友可以看完我的实现代码后,自行根据上面分析与代码不同的思路实现一遍,当做一个小练习

class ArrayQueueEntity{

    /**
     * 数组最大容量
     */
    private final int maxSize;
    /**
     * 约定指向队列头的前一个位置
     */
    private int front;
    /**
     * 指向队列尾
     */
    private int rear;
    /**
     * 模拟队列用于存放数据的数组
     */
    private final int[] arr;

    /**
     * 构造器,创建队列(初始化队列)
     * @param arrMaxSize 队列最大容量
     */
    public ArrayQueueEntity(int arrMaxSize){
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        //初始化时头指针指向第一个数据的前一个(其实表示这个位置是上一次出列的数据位置)
        front = -1;
        //初始化时尾指针需要指向当前最后一个数据的索引,但初始化队列为空找不到队尾,所以根据空队列判断尾指针-头指针=0,设置为-1
        rear = -1;
    }

    /**
     * 判断队列是否是满的
     * @return true表示队列满了,false表示队列没满
     */
    public boolean isFull(){
        return rear - front >= maxSize;
    }

    /**
     * 判断队列是否为空
     * @return true表示为空,false表示不为空
     */
    public boolean isEmpty(){
        return rear - front == 0;
    }

    /**
     * 添加数据到队列
     * @param data 要添加的数据
     */
    public void addQueue(int data){
        //判断队列是否已满
        if (!isFull()){
            //队列没满,添加数据
            //队列尾指针后移
            rear++;
            //在尾指针处添加数据(指针位置都一直在后移,所以要对数组容量取余,模拟成环形队列)
            arr[rear%maxSize] = data;
        }else {
            //队列满了输出提示
            System.out.println("队列满,不能加入数据");
        }
    }

    /**
     * 获取队列数据/出队列
     * @return 出队列的数据
     */
    public int getQueue(){
        //先判断队列是否为空
        if (isEmpty()){
            throw new RuntimeException("队列为空");
        }
        //不为空,取数据
        //头指针后移一下,指向需要出列的数据
        front++;
        //让指针位置数据出列即可
        return arr[front%maxSize];
    }

    /**
     * 打印当前队列的所有数据
     */
    public void printQueue(){
        System.out.println("正在打印当前队列......");
        //先判断队列是否为空
        if (!isEmpty()){
            //不为空就遍历打印,从头指针的下一个遍历到尾指针
            for (int i = front+1; i <= rear; i++) {
                System.out.println(i+":"+arr[i%maxSize]);
            }
        }else {
            System.out.println("队列中没有数据");
        }
    }
}

模拟上面代码,完成小练习后,可以用下面这个主方法来测试一下队列

    public static void main(String[] args) {
        //初始化队列——最大容量为3
        ArrayQueueEntity queue = new ArrayQueueEntity(3);
        //接收用户输入
        String 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):从队列取出数据");
            key = scanner.next();
            switch (key){
                case "s":
                    queue.printQueue();
                    break;
                case "e":
                    loop=false;
                    break;
                case "a":
                    if (queue.isFull()){
                        System.out.println("队列已满,清先出列一些数据再试");
                        break;
                    }
                    System.out.println("请输入要入队的数字:");
                    int data = scanner.nextInt();
                    queue.addQueue(data);
                    break;
                case "g":
                    if (queue.isEmpty()){
                        System.out.println("队列为空,没有数据可以出列,请先尝试添加数据入列");
                        break;
                    }
                    System.out.println("出列成功,出列数据为:"+queue.getQueue());
                    break;
                default:
                    System.out.println("请根据菜单提示输入正确指令");
            }
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容