
heapify(), merge()
此函數在線性時間內將 list x 轉換為 heap。
heapify(x)將多個排序輸入 *iterables,合併為一個排序輸出 (返回 iterator)。
類似於 sorted(itertools.chain(*iterables)),但返回一個 iterable 物件,不會一次將資料全部拉入內存,並假設每個輸入 streams 都已排序 (從小到大)。
在您有多個排序序列 (例如文件或 lists),並且需要將它們有效且按排序順序合併為單個 sequence 的情況下很有用。
merge(*iterables,key=None,reverse=False)key
指定一個參數的 key function,用於從每個輸入元素中提取比較 key。預設值為 None (直接比較元素)。
reverse
反轉。要實作類似 sorted(itertools.chain(*iterables), reverse=True) 的行為,所有可迭代物件都必須從最大到最小排序。
範例 – Basic Usage
Example: 在未排序的 list 中,尋找 3 個最小的元素。
Example: 合併多個排序 lists。
nlargest(), nsmallest()
從 iterable 找出 n 個最大元素。
從 iterable 找出 n 個最小元素。
範例 – Basic Usage
Example 1: Basic Usage
Example 2: 使用 key function
執行結果:
範例 – Maintained Heap
如果您需要頻繁更新集合並檢索 n 個最大或最小元素,則 Maintained heaps 或 Balanced Binary Search Tree 等資料結構可能會更有效。
在這種情況下,每次使用 heapq.nlargest 和 heapq.nsmallest 可能會效率很低,因為這些函數需要在每次呼叫時,處理整個資料集。
相反,maintaining a heap 或使用 balanced binary search tree (如, AVL Tree, Red-Black Tree) 可能會更有效。這些資料結構允許更快的插入和刪除操作,同時還提供存取最大或最小元素的有效方法。
Example 1: 假設您有一個不斷更新的 stream,並且您需要追蹤 3 個最大的元素。使用 min-heap 可能是有效的。
執行結果:
Key Takeaways
Heapq 方法: 非常適合靜態資料集或更新不頻繁的情況。
Maintained heaps: 更適合頻繁添加,但相對不頻繁刪除的場景。
Balanced BSTs: 非常適合頻繁新增和刪除的資料集,提供高效率的插入、刪除和檢索操作。
Challenges
排序穩定性和 Tuple 比較問題
排序穩定性:在優先權佇列中,您希望具有相同優先權的任務按照新增的順序進行處理。這稱為 "sort stability"。
Tuple 比較問題:如果您只是使用像
(priority, task)這樣的 tuples 作為 queue items。當優先權相等時,Python 將比較元組的兩個元素。如果task物件無法相互比較,就會出現問題。
提供的解決方案是使用 3 元素的 list or tuple,即 (priority、entry_count、task)。這就是為什麼它有效的原因:
Entry Count:這是每個任務的唯一識別碼 (如時間戳記)。當兩個任務具有相同優先權時,
heapqmodule 將比較它們的條目計數。由於這些都是唯一的,並且對於每個新任務都是遞增的,因此它確保了排序穩定性。Tuple 比較:透過條目計數,Python's tuple 比較不需要直接比較任務,從而避免了不可比較任務的問題。
解決不可比較任務問題的另一個解決方案是建立一個 wrapper class,該 class 忽略 task item 並且僅比較優先順序 field。
執行結果:
當使用 heappop() 擷取項目時,它們會依優先順序遞增的順序返回 (數字越小表示優先順序越高)。每個PrioritizedItem 實例的 item 屬性儲存實際任務,這是不可比較的,但這不會影響佇列操作,因為僅使用 priority 進行比較。
當您的任務無法相互比較,但需要確定優先順序時,此方法特別有用。 dataclasses module 可以方便地建立具有所需比較行為的結構化物件。
更改優先權和刪除任務
更改優先權:如何處理任務新增到 queue 後,優先權發生變更的情況。
刪除任務:如何從 queue 中尋找並刪除特定任務,尤其是待處理的任務。
刪除條目或更改其優先順序更加困難,因為這會破壞 heap 結構不變量。因此,一個可能的解決方案是將條目標記為已刪除,並新增具有修改優先順序的新條目:
執行結果:
參考資料
heapq — Heap queue algorithm — Python 3.12.0b4 documentation
Binary Heap Basics. In my last article I outlined the tree… | by Michael Verdi | Medium
Last updated
Was this helpful?