什麼是雙端佇列?
雙端佇列(deque)是指允許兩端都可以進行入隊和出隊操作的佇列,deque 是 “double ended queue” 的簡稱。那就說明元素可以從隊頭出隊和入隊,也可以從隊尾出隊和入隊。
雙端佇列怎麼實現?
雙端佇列的儲存結構
public class LinkedBlockingDeque<E> {
//隊頭
Node<E> first;
//隊尾
Node<E> last;
//元素個數
int count;
static final class Node<E> {
//儲存元素
E item;
//上一個元素
Node<E> prev;
//下一個元素
Node<E> next;
}
}
複製程式碼
從隊頭入隊
public boolean offerFirst(Node<E> node) {
//頭節點臨時變數
Node<E> f = first;
//把當前的下一個節點指向頭節點
node.next = f;
//更新當前節點為頭節點
first = node;
//假如尾節點為空,則把當前節點設定為尾節點
if (last == null)
last = node;
//就把以前的頭節點指向當前節點
else
f.prev = node;
//總數加一
++count;
return true;
}
複製程式碼
從隊頭出隊
public E pollFirst() {
Node<E> f = first;
//頭節點的下一個節點
Node<E> n = f.next;
//獲取頭節點元素
E item = f.item;
//置空
f.item = null;
//孤立頭節點,不指向任何節點
f.next = f; // help GC
//重置頭節點
first = n;
//說明是最後一個節點
if (n == null)
last = null;
//否則把頭節點的上一個節點置空
else
n.prev = null;
//總數減一
--count;
return item;
}
複製程式碼
從隊尾入隊
public boolean offerLast(Node<E> node) {
//尾節點臨時變數
Node<E> l = last;
if (l == null)
return null;
//把當前的上一個節點指向尾節點
node.prev = l;
//更新當前節點為尾節點
last = node;
//假如頭節點為空,則把頭節點置為當前節點
if (first == null)
first = node;
//否則把臨時的尾節點的下一個節點指向當前節點
else
l.next = node;
//總數加一
++count;
return true;
}
複製程式碼
從隊尾出隊
public E pollLast() {
Node<E> l = last;
if (l == null)
return null;
//最後節點的上一個節點
Node<E> p = l.prev;
//獲取元素
E item = l.item;
//置空
l.item = null;
//孤立尾節點
l.prev = l; // help GC
//更新尾節點
last = p;
//假如是最後一個元素,置空頭節點
if (p == null)
first = null;
//否則置空下一個節點指向
else
p.next = null;
//總數減一
--count;
return item;
}
複製程式碼
總結
雙端佇列其實和佇列差不多的,只是更加靈活了,隊頭和隊尾均可進行入隊和出隊操作。這裡是基於連結串列的雙端佇列實現,具體詳情可檢視 JDK 的 LinkedBlockingDeque 的實現,它還考慮了執行緒安全相關的東西,這裡只是簡單的一個實現,瞭解雙端佇列的結構和運作方式。