雙向佇列集合Deque

2021-08-26 07:56:39 字數 1748 閱讀 4333

queue除了前面介紹的實現外,還有一種雙向的queue實現deque。這種佇列允許在佇列頭和尾部進行入隊出隊操作,因此在功能上比queue顯然要更複雜。下圖描述的是deque的完整體系圖。需要說明的是linkedlist也已經加入了deque的一部分(linkedlist是從jdk1.2 開始就存在資料結構)。

deque在queue的基礎上增加了更多的操作方法。

從上圖可以看到,deque不僅具有fifo的queue實現,也有filo的實現,也就是不僅可以實現佇列,也可以實現乙個堆疊。

同時在deque的體系結構圖中可以看到,實現乙個deque可以使用陣列(arraydeque),同時也可以使用鍊錶(linkedlist),還可以同實現乙個支援阻塞的執行緒安全版本佇列linkedblockingdeque。

對於陣列實現的deque來說,資料結構上比較簡單,只需要乙個儲存資料的陣列以及頭尾兩個索引即可。由於陣列是固定長度的,所以很容易就得到陣列的頭和尾,那麼對於陣列的操作只需要移動頭和尾的索引即可。

特別說明的是arraydeque並不是乙個固定大小的佇列,每次佇列滿了以後就將佇列容量擴大一倍(doublecapacity()),因此加入乙個元素總是能成功,而且也不會丟擲乙個異常。也就是說arraydeque是乙個沒有容量限制的佇列。

同樣繼續效能的考慮,使用system.arraycopy複製乙個陣列比迴圈設定要高效得多。

對於linkedlist本身而言,資料結構就更簡單了,除了乙個size用來記錄大小外,只有head乙個元素entry。對比map和queue的其它資料結構可以看到這裡的entry有兩個引用,是雙向的佇列。

在示意圖中,linkedlist總是有乙個「傀儡」節點,用來描述佇列「頭部」,但是並不表示頭部元素,它是乙個執行null的空節點。

佇列一開始只有head乙個空元素,然後從尾部加入e1(add/addlast),head和e1之間建立雙向鏈結。然後繼續從尾部加入e2,e2就在head和e1之間建立雙向鏈結。最後從佇列的頭部加入e3(push/addfirst),於是e3就在e1和head之間鏈結雙向鏈結。

雙向鍊錶的資料結構比較簡單,操作起來也比較容易,從事從「傀儡」節點開始,「傀儡」節點的下乙個元素就是佇列的頭部,前乙個元素是佇列的尾部,換句話說,「傀儡」節點在頭部和尾部之間建立了乙個通道,是整個佇列形成乙個迴圈,這樣就可以從任意乙個節點的任意乙個方向能遍歷完整的佇列。

同樣linkedlist也是乙個沒有容量限制的佇列,因此入佇列(不管是從頭部還是尾部)總能成功。

上面描述的arraydeque和linkedlist是兩種不同方式的實現,通常在遍歷和節省記憶體上arraydeque更高效(索引更快,另外不需要entry物件),但是在佇列擴容下linkedlist更靈活,因為不需要複製原始的佇列,某些情況下可能更高效。

同樣需要注意的上述兩個實現都不是執行緒安全的,因此只適合在單執行緒環境下使用,下面章節要介紹的linkedblockingdeque就是執行緒安全的可阻塞的deque。事實上也應該是功能最強大的queue實現,當然了實現起來也許會複雜一點。

deque雙向佇列

deque雙向佇列是一種雙向開口的連續線性空間,可以高效的在頭尾兩端插入和刪除元素,deque在介面上和vector非常相似,下面列出deque的常用成員函式 deque的實現比較複雜,內部會維護乙個map 注意!不是stl中的map容器 即一小塊連續的空間,該空間中每個元素都是指標,指向另一段 較...

deque雙向佇列

deque雙向佇列是一種雙向開口的連續線性空間,可以高效的在頭尾兩端插入和刪除元素,deque在介面上和vector非常相似,下面列出deque的常用成員函式 deque的實現比較複雜,內部會維護乙個map 注意!不是stl中的map容器 即一小塊連續的空間,該空間中每個元素都是指標,指向另一段 較...

deque雙向佇列

deque雙向佇列是一種雙向開口的連續線性空間,可以高效的在頭尾兩端插入和刪除元素,deque在介面上和vector非常相似,下面列出deque的常用成員函式 deque的實現比較複雜,內部會維護乙個map 注意!不是stl中的map容器 即一小塊連續的空間,該空間中每個元素都是指標,指向另一段 較...