Heaps
__gnu_pbds::priority_queue
See also: Official Documentation — Complexity and Performance Tests
1 2 3 | |
Template Parameters
T: Type of stored elements.Compare: Type providing strict weak ordering comparison.Tag: One of the five different heap types provided by__gnu_pbds. The default Tag ispairing_heap_tag. The five types are:pairing_heap_tag: Pairing heap. Official documentation suggests that pairing heap performs best with non‑primitive elements (e.g., custom structs,std::string,pair).binary_heap_tag: Binary heap. Official documentation suggests that binary heap performs best with primitive elements, but the author's tests did not show such good performance.binomial_heap_tag: Binomial heap. Binomial heap outperforms binary heap in merge operations, but its top‑element access has higher complexity than binary heap.rc_binomial_heap_tag: Redundant‑counter binomial heap.thin_heap_tag: A tag whose complexities are the same as Fibonacci heap except for merging.
Allocator: Memory allocator. Rarely used in OI, so not explained here.
Since this article is intended for competitive programming learners, only the first tag will be described in detail (member functions and usage), while the latter four will only have their complexities briefly mentioned.
Tests on the author's machine (Core i5 @3.1 GHz, macOS) on basic heap operations, combined with GNU's official complexity tests and Dijkstra tests, all indicate:
At least for OIers, the other four tags besides pairing heap are either useless or have constants so large that they are worse than std's, and may even cause MLE. Therefore, only the default pairing heap is recommended here. Also, pairing heap outperforms make_heap() from the algorithm library.
Construction
The namespace must be specified because the class name conflicts with std.
1 2 3 4 5 6 | |
Member Functions
push(): Pushes an element into the heap, returns an iterator to its position.pop(): Pops the top element.top(): Returns the top element.size(): Returns the number of elements.empty(): Returns whether the heap is empty.modify(point_iterator, const key): Modifies thekeyat the iterator's position to the givenkeyand reorders the underlying storage.erase(point_iterator): Erases the key‑value at the iterator's position from the heap.join(__gnu_pbds::priority_queue &other): Mergesotherinto*thisand clearsother.
The chosen tag determines the time complexity of each operation:
| push | pop | modify | erase | Join | |
|---|---|---|---|---|---|
pairing_heap_tag |
\(O(1)\) | worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | \(O(1)\) |
binary_heap_tag |
worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | \(\Theta(n)\) | \(\Theta(n)\) | \(\Theta(n)\) |
binomial_heap_tag |
worst \(\Theta(\log(n))\) amortized \(O(1)\) | \(\Theta(\log(n))\) | \(\Theta(\log(n))\) | \(\Theta(\log(n))\) | \(\Theta(\log(n))\) |
rc_binomial_heap_tag |
\(O(1)\) | \(\Theta(\log(n))\) | \(\Theta(\log(n))\) | \(\Theta(\log(n))\) | \(\Theta(\log(n))\) |
thin_heap_tag |
\(O(1)\) | worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | worst \(\Theta(\log(n))\) amortized \(O(1)\) | worst \(\Theta(n)\) amortized \(\Theta(\log(n))\) | \(\Theta(n)\) |
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
__gnu_pbds Iterator Invalidation Guarantee (invalidation_guarantee)
In the above example and in some practical uses (e.g., using the pb‑ds heap in this chapter to implement single‑source shortest path algorithms), it is often necessary to save and use heap iterators (such as __gnu_pbds::priority_queue<int>::point_iterator).
However, for different Tag parameters of __gnu_pbds::priority_queue, the underlying implementations differ, and the conditions for iterator invalidation also vary. According to the design of the __gnu_pbds library, there are three derived cases from top to bottom:
-
Basic invalidation guarantee (basic_invalidation_guarantee): When the container is not modified, point‑type iterators (point_iterator), pointers, and references (key/value) remain valid.
-
Point invalidation guarantee (point_invalidation_guarantee): After modifying the container, point‑type iterators (point_iterator), pointers, and references (key/value) remain valid as long as the corresponding element has not been deleted from the container.
-
Range invalidation guarantee (range_invalidation_guarantee): After modifying the container, in addition to the property (2), any range‑type iterators (including the return values of
begin()andend()) are correct. Tags with range invalidation guarantee arerb_tree_tagandsplay_tree_tag(for__gnu_pbds::tree), andpat_trie_tag(for__gnu_pbds::trie).
Running the code below shows that except for binary_heap_tag, which has basic_invalidation_guarantee (iterators become invalid after modification), all others have point_invalidation_guarantee, satisfying the requirement that point‑type iterators (point_iterator) remain valid after modification.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用