Java數(shù)組模擬隊列

Java數(shù)組模擬隊列

簡介

本文主要內(nèi)容在Java代碼中用數(shù)組模擬一個隊列出來道伟,這里只簡要一提,不過多的介紹隊列基本概念

隊列是一種特殊的線性表,特點是先進先出草丧。

和棧相似,它們的操作都是受限的莹桅。

這里要說的隊列昌执,只有兩種操作,插入一個數(shù)據(jù)稱為入隊诈泼,刪除一個數(shù)據(jù)稱為出隊懂拾,并且只能從隊尾插入數(shù)據(jù),只能在隊頭刪除數(shù)據(jù)铐达。

隊列的數(shù)組實現(xiàn)

從百度百科中可以看到對隊列的描述

簡要來說岖赋,實現(xiàn)一個隊列,本質(zhì)上需要一片連續(xù)的存儲空間瓮孙,可以是靜態(tài)分配唐断,也可以動態(tài)申請

數(shù)組呢,正好就可以貼合這個要求杭抠,靜態(tài)分配一段定長的連續(xù)內(nèi)存空間

除此之外脸甘,還需要兩個指針,一個指向隊頭偏灿,一個指向隊尾

入隊操作是在隊尾添加數(shù)據(jù)丹诀,所以要在指向隊尾的指針后一個位置添加數(shù)據(jù),并且將指針指向新的隊尾翁垂,也就是尾指針后移

出隊操作是取出并刪除隊頭的數(shù)據(jù)铆遭,其實刪除數(shù)據(jù)的操作,就是在指向隊頭的指針處取得數(shù)據(jù)返回沿猜,然后將隊頭指針后移即可

我們發(fā)現(xiàn)枚荣,在操作數(shù)據(jù)的同時,需要伴隨著指針的移動

分析一把邢疙,如果將頭指針正好指向當(dāng)前隊頭棍弄,尾指針正好指向當(dāng)前隊尾

注意:完整實現(xiàn)一個隊列,需要有入隊疟游、出隊呼畸、初始化三個操作。但用數(shù)組實現(xiàn)隊列颁虐,因為存儲空間是靜態(tài)分配的定長空間蛮原,意味著隊列容量有最大值,所以還需要判斷隊列滿和隊列空兩種情況

1.入隊:將尾指針后移一下另绩,然后儒陨,將數(shù)據(jù)放到尾指針位置;(需要先判斷隊列是否還沒滿)

2.出隊:將頭指針位置的數(shù)據(jù)取出笋籽,然后蹦漠,后移頭指針;(需要先判斷是否有數(shù)據(jù)可以出隊)

3.判斷隊列的空滿問題:

這種方式下车海,在操作出入隊之前笛园,尾指針正好指向隊尾,頭指針正好指向隊頭

所以侍芝,尾指針數(shù)值 - 頭指針數(shù)值 +1 = 當(dāng)前隊列數(shù)據(jù)量研铆,我們判斷這個計算出的當(dāng)前隊列數(shù)據(jù)量,如果等于最大容量就說明隊列滿了州叠,如果等于0就說明隊列是空的

4.初始化隊列:

初始化隊列時棵红,首先分析初始化的隊列是空的,根據(jù)判斷隊列為空的方式咧栗,發(fā)現(xiàn)逆甜,當(dāng)隊列空時,頭指針在尾指針的后一個位置楼熄;再分析第一個入隊的數(shù)據(jù)要放在數(shù)組的第一個位置忆绰,也就是索引0的位置,而入隊時先將尾指針后移可岂,再將數(shù)據(jù)放在尾指針位置错敢,所以初始化尾指針要指向-1;而頭指針要在尾指針后一位缕粹,也就是初始化頭指針指向0稚茅。

5.改進:

這樣的方式實現(xiàn)隊列后,會發(fā)現(xiàn)指針一直在后移平斩,添加到最大容量后亚享,指針就會超出邊界,即便數(shù)據(jù)都已經(jīng)出列了绘面,也無法再入隊欺税,所以其實當(dāng)指針移動到最大容量位置時侈沪,再向后移應(yīng)該是移動到第一個,讓隊列首尾相連變成一個環(huán)狀

實現(xiàn)這個的方式是晚凿,每次在移動指針后進行一次(指針%最大容量)的取余運算

但這樣會出現(xiàn)問題亭罪,原先的計算當(dāng)前數(shù)據(jù)量公式就不再正確,還需要將(結(jié)果%最大容量)進行取余運算

也可以放任指針持續(xù)后移歼秽,在取數(shù)據(jù)和插入數(shù)據(jù)的時候?qū)χ羔樔∮嘤σ郏@樣不影響計算數(shù)據(jù)量公式

實現(xiàn)方式其實并不唯一,取決于你對頭尾指針的設(shè)定

下面的代碼演示中燥筷,設(shè)定為:頭指針指向隊列頭的前一個數(shù)據(jù)箩祥,尾指針指向隊列尾

區(qū)別就是:

1.判斷隊列容量:尾指針-頭指針正好等于隊列容量,不需要加一

2.入隊出隊操作都是先移動指針肆氓,再操作數(shù)據(jù)

眼觀千遍袍祖,不如手動一遍

讀者朋友可以看完我的實現(xiàn)代碼后,自行根據(jù)上面分析與代碼不同的思路實現(xiàn)一遍谢揪,當(dāng)做一個小練習(xí)

class ArrayQueueEntity{

    /**
     * 數(shù)組最大容量
     */
    private final int maxSize;
    /**
     * 約定指向隊列頭的前一個位置
     */
    private int front;
    /**
     * 指向隊列尾
     */
    private int rear;
    /**
     * 模擬隊列用于存放數(shù)據(jù)的數(shù)組
     */
    private final int[] arr;

    /**
     * 構(gòu)造器盲泛,創(chuàng)建隊列(初始化隊列)
     * @param arrMaxSize 隊列最大容量
     */
    public ArrayQueueEntity(int arrMaxSize){
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        //初始化時頭指針指向第一個數(shù)據(jù)的前一個(其實表示這個位置是上一次出列的數(shù)據(jù)位置)
        front = -1;
        //初始化時尾指針需要指向當(dāng)前最后一個數(shù)據(jù)的索引,但初始化隊列為空找不到隊尾键耕,所以根據(jù)空隊列判斷尾指針-頭指針=0寺滚,設(shè)置為-1
        rear = -1;
    }

    /**
     * 判斷隊列是否是滿的
     * @return true表示隊列滿了,false表示隊列沒滿
     */
    public boolean isFull(){
        return rear - front >= maxSize;
    }

    /**
     * 判斷隊列是否為空
     * @return true表示為空屈雄,false表示不為空
     */
    public boolean isEmpty(){
        return rear - front == 0;
    }

    /**
     * 添加數(shù)據(jù)到隊列
     * @param data 要添加的數(shù)據(jù)
     */
    public void addQueue(int data){
        //判斷隊列是否已滿
        if (!isFull()){
            //隊列沒滿村视,添加數(shù)據(jù)
            //隊列尾指針后移
            rear++;
            //在尾指針處添加數(shù)據(jù)(指針位置都一直在后移,所以要對數(shù)組容量取余酒奶,模擬成環(huán)形隊列)
            arr[rear%maxSize] = data;
        }else {
            //隊列滿了輸出提示
            System.out.println("隊列滿蚁孔,不能加入數(shù)據(jù)");
        }
    }

    /**
     * 獲取隊列數(shù)據(jù)/出隊列
     * @return 出隊列的數(shù)據(jù)
     */
    public int getQueue(){
        //先判斷隊列是否為空
        if (isEmpty()){
            throw new RuntimeException("隊列為空");
        }
        //不為空,取數(shù)據(jù)
        //頭指針后移一下惋嚎,指向需要出列的數(shù)據(jù)
        front++;
        //讓指針位置數(shù)據(jù)出列即可
        return arr[front%maxSize];
    }

    /**
     * 打印當(dāng)前隊列的所有數(shù)據(jù)
     */
    public void printQueue(){
        System.out.println("正在打印當(dāng)前隊列......");
        //先判斷隊列是否為空
        if (!isEmpty()){
            //不為空就遍歷打印杠氢,從頭指針的下一個遍歷到尾指針
            for (int i = front+1; i <= rear; i++) {
                System.out.println(i+":"+arr[i%maxSize]);
            }
        }else {
            System.out.println("隊列中沒有數(shù)據(jù)");
        }
    }
}

模擬上面代碼,完成小練習(xí)后另伍,可以用下面這個主方法來測試一下隊列

    public static void main(String[] args) {
        //初始化隊列——最大容量為3
        ArrayQueueEntity queue = new ArrayQueueEntity(3);
        //接收用戶輸入
        String key;
        Scanner scanner = new Scanner(System.in);
        //讓系統(tǒng)在用戶主動退出之前一直運行鼻百,并能夠輸出一個指引菜單
        boolean loop = true;
        while (loop){
            System.out.println("s(show):顯示當(dāng)前隊列狀況");
            System.out.println("e(exit):退出程序");
            System.out.println("a(add):添加數(shù)據(jù)到隊列");
            System.out.println("g(get):從隊列取出數(shù)據(jù)");
            key = scanner.next();
            switch (key){
                case "s":
                    queue.printQueue();
                    break;
                case "e":
                    loop=false;
                    break;
                case "a":
                    if (queue.isFull()){
                        System.out.println("隊列已滿,清先出列一些數(shù)據(jù)再試");
                        break;
                    }
                    System.out.println("請輸入要入隊的數(shù)字:");
                    int data = scanner.nextInt();
                    queue.addQueue(data);
                    break;
                case "g":
                    if (queue.isEmpty()){
                        System.out.println("隊列為空摆尝,沒有數(shù)據(jù)可以出列温艇,請先嘗試添加數(shù)據(jù)入列");
                        break;
                    }
                    System.out.println("出列成功,出列數(shù)據(jù)為:"+queue.getQueue());
                    break;
                default:
                    System.out.println("請根據(jù)菜單提示輸入正確指令");
            }
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堕汞,一起剝皮案震驚了整個濱河市勺爱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌讯检,老刑警劉巖琐鲁,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卫旱,死亡現(xiàn)場離奇詭異,居然都是意外死亡围段,警方通過查閱死者的電腦和手機誊涯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒜撮,“玉大人,你說我怎么就攤上這事跪呈《文ィ” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵耗绿,是天一觀的道長苹支。 經(jīng)常有香客問我,道長误阻,這世上最難降的妖魔是什么债蜜? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮究反,結(jié)果婚禮上寻定,老公的妹妹穿的比我還像新娘。我一直安慰自己精耐,他們只是感情好狼速,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卦停,像睡著了一般向胡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惊完,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天僵芹,我揣著相機與錄音,去河邊找鬼小槐。 笑死拇派,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凿跳。 我是一名探鬼主播攀痊,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拄显!你這毒婦竟也來了苟径?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤躬审,失蹤者是張志新(化名)和其女友劉穎棘街,沒想到半個月后蟆盐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡遭殉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年石挂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片险污。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡痹愚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛔糯,到底是詐尸還是另有隱情拯腮,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布蚁飒,位于F島的核電站动壤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏淮逻。R本人自食惡果不足惜琼懊,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爬早。 院中可真熱鬧哼丈,春花似錦、人聲如沸筛严。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脑漫。三九已至髓抑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間优幸,已是汗流浹背吨拍。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留网杆,地道東北人羹饰。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像碳却,于是被迫代替她去往敵國和親队秩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容