|
| 1 | +# Queue - 隊列 |
| 2 | + |
| 3 | +Queue 是一個 FIFO(First-in First-out, 先進先出)的資料結構,併發(concurrent)中經常使用,可以安全地將對象從一個任務傳給另一個任務。 |
| 4 | + |
| 5 | +## 程式碼實現 |
| 6 | + |
| 7 | +### Python |
| 8 | + |
| 9 | +Queue 和 Stack 在 Python 中都是用 `list` ,`[]` 實現的。 在python 中list是一個dynamic array, 可以通過`append`在list的尾部添加元素, 通過`pop()`在list的尾部彈出元素實現`Stack`的`FILO`, 如果是`pop(0)`則彈出頭部的元素實現`Queue`的`FIFO`。 |
| 10 | +```python |
| 11 | +queue = [] # same as list() |
| 12 | +size = len(queue) |
| 13 | +queue.append(1) |
| 14 | +queue.append(2) |
| 15 | +queue.pop(0) # return 1 |
| 16 | +queue[0] # return 2 examine the first element |
| 17 | +``` |
| 18 | + |
| 19 | +#### Methods |
| 20 | +| \ | methods | |
| 21 | +| -- | -- | |
| 22 | +| Insert | queue.append(e) | |
| 23 | +| Remove | queue.pop(0) | |
| 24 | +| Examine | queue[0] | |
| 25 | + |
| 26 | +### Java |
| 27 | + |
| 28 | +Queue 在 Java 中是 Interface, 一種實現是 LinkedList, LinkedList 向上轉型為 Queue, Queue 通常不能存儲 `null` 元素,否則與 `poll()` 等方法的返回值混淆。 |
| 29 | + |
| 30 | +```java |
| 31 | +Queue<Integer> q = new LinkedList<Integer>(); |
| 32 | +int qLen = q.size(); // get queue length |
| 33 | +``` |
| 34 | + |
| 35 | +#### Methods |
| 36 | + |
| 37 | +| 0:0 | Throws exception | Returns special value | |
| 38 | +| -- | -- | -- | |
| 39 | +| Insert | add(e) | offer(e) | |
| 40 | +| Remove | remove() | poll() | |
| 41 | +| Examine | element() | peek() | |
| 42 | + |
| 43 | +優先考慮右側方法,右側元素不存在時返回 `null`. 判斷非空時使用`isEmpty()`方法,繼承自 Collection. |
| 44 | + |
| 45 | +## Priority Queue - 優先隊列 |
| 46 | + |
| 47 | +應用程式常常需要處理帶有優先級的業務,優先級最高的業務首先得到服務。因此優先隊列這種資料結構應運而生。優先隊列中的每個元素都有各自的優先級,優先級最高的元素最先得到服務;優先級相同的元素按照其在優先隊列中的順序得到服務。 |
| 48 | + |
| 49 | +優先隊列可以使用陣列或鏈表實現,從時間和空間覆雜度來說,往往用二叉堆(Binary heap)來實現。 |
| 50 | + |
| 51 | +### Python |
| 52 | + |
| 53 | +Python 中提供`heapq`的lib來實現 priority queue. 提供`push`和`pop`兩個基本操作和`heapify`初始化操作. |
| 54 | + |
| 55 | +| \ | methods | time complexity | |
| 56 | +| -- | -- | -- | |
| 57 | +| enqueue | heapq.push(queue, e) | $$O(\log n)$$ | |
| 58 | +| dequeue | heapq.pop(queue) | $$O(\log n)$$ | |
| 59 | +| init | heapq.heapify(queue) | $$O(n\log n)$$ | |
| 60 | +| peek | queue[0]| $$O(1)$$ | |
| 61 | + |
| 62 | + |
| 63 | +### Java |
| 64 | + |
| 65 | +Java 中提供`PriorityQueue`類,該類是 Interface Queue 的另外一種實現,和`LinkedList`的區別主要在於排序行為而不是性能,基於 priority heap 實現,非`synchronized`,故多執行緒(Multi-thread)下應使用`PriorityBlockingQueue`. 預設為自然序(小根堆),需要其他排序方式可自行實現`Comparator`接口,選用合適的構造器初始化。使用叠代器遍歷時不保證有序,有序訪問時需要使用`Arrays.sort(pq.toArray())`. |
| 66 | + |
| 67 | +不同方法的時間覆雜度: |
| 68 | + |
| 69 | +- enqueuing and dequeuing: `offer`, `poll`, `remove()` and `add` - $$O(\log n)$$ |
| 70 | +- Object: `remove(Object)` and `contains(Object)` - $$O(n)$$ |
| 71 | +- retrieval: `peek`, `element`, and `size` - $$O(1)$$. |
| 72 | + |
| 73 | +## Deque - 雙端隊列 |
| 74 | + |
| 75 | +雙端隊列(deque,全名double-ended queue)可以讓你在任何一端添加或者移除元素,因此它是一種具有隊列和堆疊性質的資料結構。 |
| 76 | + |
| 77 | +### Python |
| 78 | + |
| 79 | +Python 的`list`就可以執行類似於`deque`的操作, 但是效率會過於慢。 為了提升數據的處理效率, 一些高效的資料結構放在了`collections`中。 在`collections` 中提供了`deque`的類, 如果需要多次對`list`執行頭尾元素的操作, 請使用`deque`。 |
| 80 | + |
| 81 | +```python |
| 82 | +dq = collections.deque(); |
| 83 | +``` |
| 84 | + |
| 85 | +#### Methods |
| 86 | + |
| 87 | +| \ | methods | time complexity | |
| 88 | +| -- | -- | -- | |
| 89 | +| enqueue left | dq.appendleft(e) | $$O(1)$$ | |
| 90 | +| enqueue right | dq.append(e) | $$O(1)$$ | |
| 91 | +| dequeue left | dq.popleft() | $$O(1)$$ | |
| 92 | +| dequeue right | dq.pop() | $$O(1)$$ | |
| 93 | +| peek left | dq[0] | $$O(1)$$ | |
| 94 | +| peek right | dq[-1] | $$O(1)$$ | |
| 95 | + |
| 96 | +### Java |
| 97 | + |
| 98 | +Java 在1.6之後提供了 Deque 介面,既可使用`ArrayDeque`(陣列)來實現,也可以使用`LinkedList`(鏈表)來實現。前者是一個數組外加首尾索引,後者是雙向鏈表。 |
| 99 | + |
| 100 | +```java |
| 101 | +Deque<Integer> deque = new ArrayDeque<Integer>(); |
| 102 | +``` |
| 103 | + |
| 104 | +#### Methods |
| 105 | + |
| 106 | +<table> |
| 107 | + <tr> |
| 108 | + <td></td> |
| 109 | + <td colspan="2">First Element (Head)</td> |
| 110 | + <td colspan="2">Last Element (Tail)</td> |
| 111 | + </tr> |
| 112 | + <tr> |
| 113 | + <td></td> |
| 114 | + <td>Throws exception</td> |
| 115 | + <td>Special value</td> |
| 116 | + <td>Throws exception</td> |
| 117 | + <td>Special value</td> |
| 118 | + </tr> |
| 119 | + <tr> |
| 120 | + <td>Insert</td> |
| 121 | + <td>`addFirst(e)`</td> |
| 122 | + <td>`offerFirst(e)`</td> |
| 123 | + <td>`addLast(e)`</td> |
| 124 | + <td>`offerLast(e)`</td> |
| 125 | + </tr> |
| 126 | + <tr> |
| 127 | + <td>Remove</td> |
| 128 | + <td>`removeFirst()`</td> |
| 129 | + <td>`pollFirst()`</td> |
| 130 | + <td>`removeLast()`</td> |
| 131 | + <td>`pollLast()`</td> |
| 132 | + </tr> |
| 133 | + <tr> |
| 134 | + <td>Examine</td> |
| 135 | + <td>`getFirst()`</td> |
| 136 | + <td>`peekFirst()`</td> |
| 137 | + <td>`getLast()`</td> |
| 138 | + <td>`peekLast()`</td> |
| 139 | + </tr> |
| 140 | +</table> |
| 141 | + |
| 142 | +其中`offerLast`和 Queue 中的`offer`功能相同,都是從尾部插入。 |
| 143 | + |
| 144 | +## Reference |
| 145 | + |
| 146 | +- [優先隊列 - 維基百科,自由的百科全書](http://zh.wikipedia.org/zh/%E5%84%AA%E5%85%88%E4%BD%87%E5%88%97) |
| 147 | +- [雙端隊列 - 維基百科,自由的百科全書](https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97) |
0 commit comments