Heap
__gnu_pbds::priority_queue
Kèm theo: Tài liệu chính thức — kiểm thử độ phức tạp và hằng số
1 2 3 | |
Tham số mẫu
T: kiểu phần tử lưu trữCompare: kiểu so sánh weak order nghiêm ngặtTag: 5 loại heap khác nhau của__gnu_pbds, mặc định làpairing_heap_tag:pairing_heap_tag: pairing heap Tài liệu chính thức cho rằng với phần tử không nguyên thủy (như struct tự định nghĩa/std::string/pair), pairing heap tốt nhấtbinary_heap_tag: binary heap Tài liệu chính thức cho rằng với phần tử nguyên thủy, binary heap tốt nhất, nhưng người viết thử nghiệm thấy không hẳnbinomial_heap_tag: binomial heap Binomial heap tốt hơn binary heap ở phép gộp, nhưng thao tác lấy đỉnh có độ phức tạp cao hơnrc_binomial_heap_tag: redundant-counting binomial heapthin_heap_tag: một tag mà mọi độ phức tạp ngoài phép gộp đều giống Fibonacci heap
Allocator: bộ cấp phát; ít gặp trong OI nên không bàn ở đây
Bài này chủ yếu phục vụ học sinh thi đấu, nên chỉ giới thiệu ngắn gọn độ phức tạp của bốn tag sau; tag đầu sẽ giới thiệu hàm và cách dùng.
Theo thử nghiệm trên máy tác giả (Core i5 @3.1 GHz, macOS), kết hợp kiểm thử độ phức tạp GNU và kiểm thử Dijkstra:
Ít nhất đối với OIer, bốn tag ngoài pairing heap đều kém hiệu quả: hoặc không hữu dụng, hoặc hằng số lớn hơn std, thậm chí có thể MLE. Vì vậy chỉ khuyến nghị dùng pairing heap mặc định. Đồng thời, pairing heap cũng tốt hơn make_heap() của algorithm.
Cách khởi tạo
Cần chỉ rõ namespace vì trùng tên với std.
1 2 3 4 5 6 | |
Hàm thành viên
push(): đẩy một phần tử vào heap, trả iterator vị trí phần tử đó.pop(): loại bỏ phần tử đỉnh.top(): trả phần tử đỉnh.size()trả số lượng phần tử.empty()trả về có rỗng hay không.modify(point_iterator, const key): sửa khóa tại iterator thànhkeymới và sắp xếp lại cấu trúc lưu trữ.erase(point_iterator): xóa phần tử tại iterator.join(__gnu_pbds::priority_queue &other): gộpothervào*thisvà làm rỗngother.
Độ phức tạp phụ thuộc vào tag:
| push | pop | modify | erase | Join | |
|---|---|---|---|---|---|
pairing_heap_tag |
\(O(1)\) | tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | \(O(1)\) |
binary_heap_tag |
tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | \(\Theta(n)\) | \(\Theta(n)\) | \(\Theta(n)\) |
binomial_heap_tag |
tối đa \(\Theta(\log(n))\), trung bình \(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)\) | tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | tối đa \(\Theta(\log(n))\), trung bình \(O(1)\) | tối đa \(\Theta(n)\), trung bình \(\Theta(\log(n))\) | \(\Theta(n)\) |
Ví dụ
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 | |
Bảo đảm hiệu lực iterator trong __gnu_pbds (invalidation_guarantee)
Trong ví dụ ở trên và thực tế (ví dụ dùng heap pb-ds để viết Dijkstra), ta thường cần lưu và dùng iterator của heap (như __gnu_pbds::priority_queue<int>::point_iterator).
Tuy nhiên với các Tag khác nhau, hiện thực nền khác nhau nên điều kiện mất hiệu lực iterator cũng khác. Theo thiết kế của __gnu_pbds, có ba mức bảo đảm (từ cao xuống thấp):
-
Bảo đảm cơ bản (basic_invalidation_guarantee): khi không sửa container, point_iterator, pointer và reference (key/value) vẫn hợp lệ.
-
Bảo đảm điểm (point_invalidation_guarantee): khi sửa container, point_iterator, pointer và reference (key/value) tương ứng vẫn hợp lệ nếu phần tử đó chưa bị xóa.
-
Bảo đảm phạm vi (range_invalidation_guarantee): khi sửa container, ngoài (2) thì mọi iterator phạm vi (kể cả
begin()vàend()) đều đúng; các Tag có bảo đảm này gồmrb_tree_tagvàsplay_tree_tag(dùng cho__gnu_pbds::tree) vàpat_trie_tag(dùng cho__gnu_pbds::trie).
Chạy đoạn code dưới cho thấy, trừ binary_heap_tag có basic_invalidation_guarantee nên iterator sẽ mất hiệu lực sau khi sửa, các tag còn lại đều là point_invalidation_guarantee, đáp ứng yêu cầu point_iterator không mất hiệu lực sau khi sửa.
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 | |
Last updated on this page:, Update history
Found an error? Want to help improve? Edit this page on GitHub!
Contributors to this page:Xeonacid, ouuan, Ir1d, WAAutoMaton, Chrogeek, abc1763613206, Planet6174, i-Yirannn, opsiff, GoodCoder666
All content on this page is provided under the terms of the CC BY-SA 4.0 and SATA license, additional terms may apply