佇列(queue)的定義,佇列的儲存結構
佇列定義
佇列(queue )簡稱隊,它同堆疊一樣,也是一種運算受限的線性表,
其限制是僅允許在表的一端進行插入,而在表的另一端進行刪除。
在佇列中把插入資料元素的一端稱為 隊尾(rear) ),刪除資料元素的一端稱為 隊首(front) )。
向隊尾插入元素稱為 進隊或入隊,新元素入隊後成為新的隊尾元素;
從佇列中刪除元素稱為 離隊或出隊,元素出隊後,其後續元素成為新的隊首元素。
由於佇列的插入和刪除操作分別在隊尾和隊首進行,每個元素必然按照進入的次序離隊,
也就是說先進隊的元素必然先離隊,所以稱佇列為 先進先出表(First In First Out,簡稱FIFO)。
生活案例:排隊打飯,排隊進地鐵站,上地鐵
技術案例:多執行緒中就緒佇列和阻塞佇列
對於佇列的主要操作是入隊和出隊操作
public interface Queue { // 返回佇列的大小 public int getSize(); // 判斷佇列是否為空 public boolean isEmpty(); // 資料元素 e 入隊 public void enqueue(Object e); // 隊首元素出隊 public Object dequeue(); // 取隊首元素 public Object peek(); }
佇列的儲存結構
順序佇列
方法1:使用陣列作為儲存結構:
缺點:通過出隊操作將資料彈出佇列後,front之前的空間還能夠再次得到嗎?
不能。所以使用普通陣列實現佇列,就再也不能使用front之前的空間了,這會導致大量空間丟失
方法2:使用迴圈陣列作為儲存結構:
為了解決這個問題,將普通陣列換成迴圈陣列。在迴圈陣列中,末尾元素的下一個元素不是陣列外,而是陣列的頭元素。
這樣就能夠再次使用front之前的儲存空間了
鏈式佇列
佇列的鏈式儲存可以使用單鏈表來實現。
為了操作實現方便,這裡採用帶頭結點的單鏈表結構。
根據單鏈表的特點,選擇連結串列的頭部作為隊首,連結串列的尾部作為隊尾。
除了連結串列頭結點需要通過一個引用來指向之外,還需要一個對連結串列尾結點的引用,以方便佇列的入隊操作的實現。
為此一共設定兩個指標,一個隊首指標和一個隊尾指標,如圖 所示。
隊首指標指向隊首元素的前一個結點,即始終指向連結串列空的頭結點,隊尾指標指向隊列當前隊尾元素所在的結點。
當佇列為空時,隊首指標與隊尾指標均指向空的頭結點
雙端佇列
deque double ended queue 通常讀為“deck”
所謂雙端佇列是指兩端都可以進行進隊和出隊操作的佇列,如下圖所示,將佇列的兩端分別稱為前端和後端,兩端都可以入隊和出隊。其元素的邏輯結構仍是線性結構
在雙端佇列進隊時:前端進的元素排列在佇列中後端進的元素的前面,後端進的元素排列在佇列中前端進的元素的後面。在雙端隊列出隊時,無論前端出還是後端出,先出的元素排列在後出的元素的前面。
輸出受限的雙端佇列,即一個端點允許插入和刪除,另一個端點只允許插入的雙端佇列。
輸入受限的雙端佇列,即一個端點允許插入和刪除,另一個端點只允許刪除的雙端佇列。