數據結構——隊列

目錄

1、什么是隊列

2、隊列的實現

2.1、基于簡單循環數組的實現
2.1.1、為什么需要循環數組
2.1.2、代碼實現
2.1.3、性能和局限性
2.2、基于動態循環數組的實現
2.2.1、代碼實現
2.2.2、性能
2.3、基于鏈表的實現方法
2.3.1、代碼實現
2.3.2、性能

正文

1、什么是隊列

  • 定義:隊列是一種只能在一端插入(隊尾),在另一端刪除(隊首)的有序線性表。
  • 在隊列中插入一個元素,稱為入隊(EnQueue)。從隊列中刪除一個元素,稱為出隊(DeQueue)。試圖對一個空隊列執行出隊操作稱為下溢(underflow),試圖對一個滿隊列執行入隊操作稱為溢出(overflow)。


    圖1-1 隊列

2、隊列的實現

  • 基于簡單循環數組的實現
  • 基于動態循環數組的實現
  • 基于鏈表的實現方法
2.1、基于簡單循環數組的實現
2.1.1、為什么需要循環數組
  • 首先,分析是否可以借鑒基于簡單數組實現棧的方法來實現隊列。由隊列的定義可知,只能在一端執行插入操作,而在另一端執行刪除操作。當執行多次操作之后,出現如下問題,數組中靠前的空間浪費。


    圖2-1 簡單數組實現隊列
  • 為了解決這個問題,假設數組是循環存儲的方式,即將數組最后一個元素和第一個元素看作是連續的。依據這個假設,如果數組前端有空閑的空間,指向隊尾的指針就能夠很容易地移動到下一個空閑的位置。


    圖2-2 簡單循環數組實現隊列
  • 在數組中,采用循環增加元素的方式,并使用兩個變量分別記錄隊首元素和隊尾元素。由于是固定大小的數組,可能會出現數組被填滿的情況。這是如果執行入隊操作,將拋出“隊列滿異常”。
2.1.2、代碼實現
public class ArrayQueue {
    private int front;
    private int rear;
    private int capacity;
    private int[] array;

    //初始化
    private ArrayQueue(int size){
        capacity=size;
        front=-1;
        rear=-1;
        array=new int[size];
    }

    //創隊列
    public static ArrayQueue createQueue(int size){
        return new ArrayQueue(size);
    }

    //是否空隊列
    public boolean isEmpty(){
        return (front==-1);
    }

    //是否滿隊列
    public boolean isFull(){
        return ((rear+1)%capacity==front);
    }

    //隊列大小
    public int getQueueSize(){
        return ((capacity-front+rear+1)%capacity);
    }

    //出隊
    public int deQueue(){
        int data=-1;
        if(isEmpty()){
            return data;
        }else {
            data=array[front];
            if(front==rear){
                //空隊列
                front=rear=-1;
            }else {
                front=(front+1)%capacity;
            }
        }
        return data;
    }

    //入隊
    public void enQueue(int data){
        if(isFull()){
            return;
        }
        else {
            rear=(rear+1)%capacity;
            array[rear]=data;
            if(front==-1){
                front=rear;
            }
        }
    }
}
2.1.3、性能和局限性
  • 性能:


    圖2-3 基于簡單循環數組實現性能
  • 局限性:用于實現隊列的數組的最大空間必須預先聲明且不能改變。試圖對一個滿隊列執行入隊操作會產生異常。
2.2、基于動態循環數組的實現
  • 與簡單循環數組的區別在于,試圖對一個滿隊列執行入隊操作時,會動態增加數組的大小,使之可以成功入隊元素。
2.2.1、代碼實現
public class DynArrayQueue {
    private int front;
    private int rear;
    private int capacity;
    private int[] array;

    //構造函數
    private DynArrayQueue(){
        capacity=1;
        front=-1;
        rear=-1;
        array=new int[1];
    }

    //創隊列
    public static DynArrayQueue createDynArrayQueue(){
        return new DynArrayQueue();
    }

    //是否空隊列
    public boolean isEmpty(){
        return (front==-1);
    }

    //是否滿隊列
    public boolean isFull(){
        return ((rear+1)%capacity==front);
    }

    //隊列大小
    public int getQueueSize(){
        if(front==-1){
            return 0;
        }
        int size=(capacity-front+rear+1)%capacity;
        if(size==0){
            return capacity;
        }else {
            return size;
        }
    }

    //重置數組
    public void resizeQueue(){
        int initCapacity=capacity;
        capacity*=2;
        int[] oldArray=array;
        array=new int[this.capacity];
        for(int i=0;i<oldArray.length;i++){
            array[i]=oldArray[i];
        }
        if(rear<front){
            for(int i=0;i<front;i++){
                array[i+initCapacity]=this.array[i];
                array[i]=-1;
            }
            rear=rear+initCapacity;
        }
    }

    //入隊
    public void enQueue(int data){
        if(isFull()){
            resizeQueue();
        }
        rear=(rear+1)%capacity;
        array[rear]=data;
        if(front==-1){
            front=rear;
        }
    }

    //出隊
    public int deQueue(){
        int data=-1;
        if(this.isEmpty()){
            return data;
        }else {
            data=array[front];
            if(front==rear){
                //空隊列
                front=rear=-1;
            }else {
                front=(front+1)%capacity;
            }
        }
        return data;
    }
}
2.2.2、性能
圖2-4 基于動態循環數組實現性能
2.3、基于鏈表的實現方法
  • 通過在鏈表的末端插入元素的方法實現入隊操作,通過刪除鏈表表頭元素的方法實現出隊操作。


    圖2-5 鏈表實現隊列
2.3.1、代碼實現
public class LLQueue {
    private ListNode frontNode;
    private ListNode rearNode;

    //構造函數
    private LLQueue(){
        this.frontNode=null;
        this.rearNode=null;
    }

    //創隊列
    public static LLQueue creteQueue(){
        return new LLQueue();
    }

    //是否空隊列
    public boolean isEmpty(){
        return (frontNode==null);
    }

    //入隊
    public void enQueue(int data){
        ListNode newNode=new ListNode(data);
        if(rearNode!=null){
            rearNode.setNext(newNode);
        }
        rearNode=newNode;
        if(frontNode==null){
            frontNode=rearNode;
        }
    }

    //出隊
    public int deQueue(){
        int data=-1;
        if(isEmpty()){
            return data;
        }else {
            data=frontNode.getData();
            frontNode=frontNode.getNext();
        }
        return data;
    }
}
2.3.2、性能
圖2-6 基于鏈表實現性能
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容