資料結構之「雙端佇列」

清塵閒聊發表於2019-03-22

什麼是雙端佇列?

雙端佇列(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 的實現,它還考慮了執行緒安全相關的東西,這裡只是簡單的一個實現,瞭解雙端佇列的結構和運作方式。

相關文章