資料結構筆記——佇列

Android機動車發表於2018-03-26

定義

佇列(Queue):是隻允許在一端進行插入操作,而在另一端進行刪除操作的線性表

佇列是一種先進先出的線性表。允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。

如下圖所示:

這裡寫圖片描述

迴圈佇列

線性表有順序儲存和鏈式儲存,棧是線性表,所以有這兩種儲存方式。同樣,佇列作為一種特殊的線性表,也同樣存在這兩種儲存方式。

佇列順序儲存的不足

假設有一個佇列有n個元素,則順序儲存的佇列需要建立一個大於n的陣列,並把佇列的所有元素儲存在陣列的前n個單元,陣列下標為0的一端即是隊頭。所謂的入隊操作,其實就是在隊尾追加一個元素,不需要移動任何元素,因此世家複雜度為O(1)。

這裡寫圖片描述

與棧不同的是,佇列元素的出隊是在隊頭,即下標為0的位置,也就意味著,佇列中的所有元素都得向前移動,也就是下標為0的位置不為空,時間複雜度為O(n).

這裡寫圖片描述

它們的具體實現和線性表的順序儲存結構是一樣的,不再累贅。

但是

如果不去限制佇列的元素必須儲存在陣列的前n個單元這一條件,出隊的效能就會大大增加,如圖

這裡寫圖片描述

為了避免只有一個元素時,隊頭和隊尾重合使得處理變得麻煩,就引入兩個指標,front指向隊頭元素,rear指向隊尾元素的下一個位置,這樣當front等於rear時,表示空佇列。

這樣又出現一個問題,如果隊尾已有元素,再插入新元素時rear指向哪裡?而且,當佇列中只有隊尾有元素時,向後再加,就會產生陣列越界錯誤,可實際上之前的位置可能有空,我們把這種現象叫做假溢位

迴圈佇列定義

解決假溢位的辦法就是後面滿了,就再從頭開始,也就是頭尾相接的迴圈。我們把佇列的這種頭尾相接的順序儲存結構稱為迴圈佇列。

下標2、3、4位置已有元素,在插入新元素,則存放下標為0的位置。如圖:

這裡寫圖片描述

但之前約定當front==rear時,表示佇列為空,上述方法中front==rear時還表示佇列已滿,怎麼處理呢?

我們要求,佇列滿時,陣列中還有一個空閒單元,如圖:

這裡寫圖片描述

得出以下公式:

  • 佇列滿 的條件(rear+1)%QueueSize==front

  • 佇列長度公式:(rear-front+QueueSize)%QueueSize

佇列的鏈式儲存

佇列的鏈式儲存結構,其實就是線性表的單連結串列,只不過它只能尾進頭出而已,我們簡稱為鏈佇列。

這裡寫圖片描述

空佇列時,front和rear都指向頭節點:

這裡寫圖片描述

入隊操作

這裡寫圖片描述

  1. 將最後一個元素後繼指向新元素;
  2. 將尾指標指向新元素。

出隊操作

這裡寫圖片描述

  1. 將頭結點的後繼改為後面一位結點;
  2. 若除頭節點外只剩一個元素時,將rear指向頭節點。

總的來說,在可以確定佇列長度最大值的情況下,建議用迴圈佇列,如果你無法預估佇列的長度時,則用鏈佇列。

更多精彩內容,歡迎關注我的微信公眾號——Android機動車

這裡寫圖片描述

相關文章