File indexing completed on 2025-07-05 08:36:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP
0014 #define BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP
0015
0016 #include <boost/intrusive/detail/config_begin.hpp>
0017 #include <boost/intrusive/intrusive_fwd.hpp>
0018
0019 #include <cstddef>
0020
0021 #include <boost/intrusive/detail/assert.hpp>
0022 #include <boost/intrusive/detail/algo_type.hpp>
0023 #include <boost/intrusive/bstree_algorithms.hpp>
0024
0025 #if defined(BOOST_HAS_PRAGMA_ONCE)
0026 # pragma once
0027 #endif
0028
0029 namespace boost {
0030 namespace intrusive {
0031
0032 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0033
0034 namespace detail
0035 {
0036
0037 template<class ValueTraits, class NodePtrPrioCompare, class ExtraChecker>
0038 struct treap_node_extra_checker
0039 : public ExtraChecker
0040 {
0041 typedef ExtraChecker base_checker_t;
0042 typedef ValueTraits value_traits;
0043 typedef typename value_traits::node_traits node_traits;
0044 typedef typename node_traits::const_node_ptr const_node_ptr;
0045
0046 typedef typename base_checker_t::return_type return_type;
0047
0048 treap_node_extra_checker(const NodePtrPrioCompare& prio_comp, ExtraChecker extra_checker)
0049 : base_checker_t(extra_checker), prio_comp_(prio_comp)
0050 {}
0051
0052 void operator () (const_node_ptr p,
0053 const return_type& check_return_left, const return_type& check_return_right,
0054 return_type& check_return)
0055 {
0056 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_traits::get_left(p) || !prio_comp_(node_traits::get_left(p), p));
0057 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_traits::get_right(p) || !prio_comp_(node_traits::get_right(p), p));
0058 base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
0059 }
0060
0061 const NodePtrPrioCompare prio_comp_;
0062 };
0063
0064 }
0065
0066 #endif
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 template<class NodeTraits>
0107 class treap_algorithms
0108 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0109 : public bstree_algorithms<NodeTraits>
0110 #endif
0111 {
0112 public:
0113 typedef NodeTraits node_traits;
0114 typedef typename NodeTraits::node node;
0115 typedef typename NodeTraits::node_ptr node_ptr;
0116 typedef typename NodeTraits::const_node_ptr const_node_ptr;
0117
0118
0119 private:
0120
0121 typedef bstree_algorithms<NodeTraits> bstree_algo;
0122
0123 class rerotate_on_destroy
0124 {
0125 rerotate_on_destroy& operator=(const rerotate_on_destroy&);
0126
0127 public:
0128 rerotate_on_destroy(node_ptr header, node_ptr p, std::size_t &n)
0129 : header_(header), p_(p), n_(n), remove_it_(true)
0130 {}
0131
0132 ~rerotate_on_destroy()
0133 {
0134 if(remove_it_){
0135 rotate_up_n(header_, p_, n_);
0136 }
0137 }
0138
0139 void release()
0140 { remove_it_ = false; }
0141
0142 const node_ptr header_;
0143 const node_ptr p_;
0144 std::size_t &n_;
0145 bool remove_it_;
0146 };
0147
0148 static void rotate_up_n(const node_ptr header, const node_ptr p, std::size_t n)
0149 {
0150 node_ptr p_parent(NodeTraits::get_parent(p));
0151 node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
0152 while(n--){
0153 if(p == NodeTraits::get_left(p_parent)){
0154 bstree_algo::rotate_right(p_parent, p, p_grandparent, header);
0155 }
0156 else{
0157 bstree_algo::rotate_left(p_parent, p, p_grandparent, header);
0158 }
0159 p_parent = p_grandparent;
0160 p_grandparent = NodeTraits::get_parent(p_parent);
0161 }
0162 }
0163
0164
0165
0166 public:
0167
0168
0169 struct insert_commit_data
0170
0171 : public bstree_algo::insert_commit_data
0172
0173 {
0174
0175 inline insert_commit_data()
0176 : bstree_algo::insert_commit_data(), rotations()
0177 {}
0178
0179 std::size_t rotations;
0180
0181 };
0182
0183 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0184
0185
0186 static node_ptr get_header(const_node_ptr n) BOOST_NOEXCEPT;
0187
0188
0189 static node_ptr begin_node(const_node_ptr header) BOOST_NOEXCEPT;
0190
0191
0192 static node_ptr end_node(const_node_ptr header) BOOST_NOEXCEPT;
0193
0194
0195 static void swap_tree(node_ptr header1, node_ptr header2) BOOST_NOEXCEPT;
0196
0197
0198 static void swap_nodes(node_ptr node1, node_ptr node2) BOOST_NOEXCEPT;
0199
0200
0201 static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) BOOST_NOEXCEPT;
0202
0203
0204 static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) BOOST_NOEXCEPT;
0205
0206
0207 static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) BOOST_NOEXCEPT;
0208 #endif
0209
0210
0211 template<class NodePtrPriorityCompare>
0212 static void unlink(node_ptr n, NodePtrPriorityCompare pcomp)
0213 {
0214 node_ptr x = NodeTraits::get_parent(n);
0215 if(x){
0216 while(!bstree_algo::is_header(x))
0217 x = NodeTraits::get_parent(x);
0218 erase(x, n, pcomp);
0219 }
0220 }
0221
0222 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0223
0224 static node_ptr unlink_leftmost_without_rebalance(node_ptr header) BOOST_NOEXCEPT;
0225
0226
0227 static bool unique(const_node_ptr n) BOOST_NOEXCEPT;
0228
0229
0230 static std::size_t size(const_node_ptr header) BOOST_NOEXCEPT;
0231
0232
0233 static node_ptr next_node(node_ptr n) BOOST_NOEXCEPT;
0234
0235
0236 static node_ptr prev_node(node_ptr n) BOOST_NOEXCEPT;
0237
0238
0239 static void init(node_ptr n) BOOST_NOEXCEPT;
0240
0241
0242 static void init_header(node_ptr header) BOOST_NOEXCEPT;
0243 #endif
0244
0245
0246 template<class NodePtrPriorityCompare>
0247 static node_ptr erase(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp)
0248 {
0249 rebalance_for_erasure(header, z, pcomp);
0250 bstree_algo::erase(header, z);
0251 return z;
0252 }
0253
0254 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0255
0256 template <class Cloner, class Disposer>
0257 static void clone
0258 (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer);
0259
0260
0261 template<class Disposer>
0262 static void clear_and_dispose(node_ptr header, Disposer disposer) BOOST_NOEXCEPT;
0263
0264
0265 template<class KeyType, class KeyNodePtrCompare>
0266 static node_ptr lower_bound
0267 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0268
0269
0270 template<class KeyType, class KeyNodePtrCompare>
0271 static node_ptr upper_bound
0272 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0273
0274
0275 template<class KeyType, class KeyNodePtrCompare>
0276 static node_ptr find
0277 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0278
0279
0280 template<class KeyType, class KeyNodePtrCompare>
0281 static std::pair<node_ptr, node_ptr> equal_range
0282 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0283
0284
0285 template<class KeyType, class KeyNodePtrCompare>
0286 static std::pair<node_ptr, node_ptr> bounded_range
0287 (const_node_ptr header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
0288 , bool left_closed, bool right_closed);
0289
0290
0291 template<class KeyType, class KeyNodePtrCompare>
0292 static std::size_t count(const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0293
0294 #endif
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 template<class NodePtrCompare, class NodePtrPriorityCompare>
0312 static node_ptr insert_equal_upper_bound
0313 (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp)
0314 {
0315 insert_commit_data commit_data;
0316 bstree_algo::insert_equal_upper_bound_check(h, new_node, comp, commit_data);
0317 rebalance_check_and_commit(h, new_node, pcomp, commit_data);
0318 return new_node;
0319 }
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336 template<class NodePtrCompare, class NodePtrPriorityCompare>
0337 static node_ptr insert_equal_lower_bound
0338 (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp)
0339 {
0340 insert_commit_data commit_data;
0341 bstree_algo::insert_equal_lower_bound_check(h, new_node, comp, commit_data);
0342 rebalance_check_and_commit(h, new_node, pcomp, commit_data);
0343 return new_node;
0344 }
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364 template<class NodePtrCompare, class NodePtrPriorityCompare>
0365 static node_ptr insert_equal
0366 (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp)
0367 {
0368 insert_commit_data commit_data;
0369 bstree_algo::insert_equal_check(h, hint, new_node, comp, commit_data);
0370 rebalance_check_and_commit(h, new_node, pcomp, commit_data);
0371 return new_node;
0372 }
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392 template<class NodePtrPriorityCompare>
0393 static node_ptr insert_before
0394 (node_ptr header, node_ptr pos, node_ptr new_node, NodePtrPriorityCompare pcomp)
0395 {
0396 insert_commit_data commit_data;
0397 bstree_algo::insert_before_check(header, pos, commit_data);
0398 rebalance_check_and_commit(header, new_node, pcomp, commit_data);
0399 return new_node;
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419 template<class NodePtrPriorityCompare>
0420 static void push_back(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp)
0421 {
0422 insert_commit_data commit_data;
0423 bstree_algo::push_back_check(header, commit_data);
0424 rebalance_check_and_commit(header, new_node, pcomp, commit_data);
0425 }
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444 template<class NodePtrPriorityCompare>
0445 static void push_front(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp)
0446 {
0447 insert_commit_data commit_data;
0448 bstree_algo::push_front_check(header, commit_data);
0449 rebalance_check_and_commit(header, new_node, pcomp, commit_data);
0450 }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 template<class KeyType, class KeyNodePtrCompare, class PrioType, class PrioNodePtrPrioCompare>
0487 static std::pair<node_ptr, bool> insert_unique_check
0488 ( const_node_ptr header
0489 , const KeyType &key, KeyNodePtrCompare comp
0490 , const PrioType &prio, PrioNodePtrPrioCompare pcomp
0491 , insert_commit_data &commit_data)
0492 {
0493 std::pair<node_ptr, bool> ret =
0494 bstree_algo::insert_unique_check(header, key, comp, commit_data);
0495 if(ret.second)
0496 rebalance_after_insertion_check(header, commit_data.node, prio, pcomp, commit_data.rotations);
0497 return ret;
0498 }
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539 template<class KeyType, class KeyNodePtrCompare, class PrioType, class PrioNodePtrPrioCompare>
0540 static std::pair<node_ptr, bool> insert_unique_check
0541 ( const_node_ptr header, node_ptr hint
0542 , const KeyType &key, KeyNodePtrCompare comp
0543 , const PrioType &prio, PrioNodePtrPrioCompare pcomp
0544 , insert_commit_data &commit_data)
0545 {
0546 std::pair<node_ptr, bool> ret =
0547 bstree_algo::insert_unique_check(header, hint, key, comp, commit_data);
0548 if(ret.second)
0549 rebalance_after_insertion_check(header, commit_data.node, prio, pcomp, commit_data.rotations);
0550 return ret;
0551 }
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 static void insert_unique_commit
0571 (node_ptr header, node_ptr new_node, const insert_commit_data &commit_data) BOOST_NOEXCEPT
0572 {
0573 bstree_algo::insert_unique_commit(header, new_node, commit_data);
0574 rotate_up_n(header, new_node, commit_data.rotations);
0575 }
0576
0577
0578 template<class NodePtrCompare, class PrioNodePtrPrioCompare>
0579 static bool transfer_unique
0580 (node_ptr header1, NodePtrCompare comp, PrioNodePtrPrioCompare pcomp, node_ptr header2, node_ptr z)
0581 {
0582 insert_commit_data commit_data;
0583 bool const transferable = insert_unique_check(header1, z, comp, z, pcomp, commit_data).second;
0584 if(transferable){
0585 erase(header2, z, pcomp);
0586 insert_unique_commit(header1, z, commit_data);
0587 }
0588 return transferable;
0589 }
0590
0591
0592 template<class NodePtrCompare, class PrioNodePtrPrioCompare>
0593 static void transfer_equal
0594 (node_ptr header1, NodePtrCompare comp, PrioNodePtrPrioCompare pcomp, node_ptr header2, node_ptr z)
0595 {
0596 insert_commit_data commit_data;
0597 bstree_algo::insert_equal_upper_bound_check(header1, z, comp, commit_data);
0598 rebalance_after_insertion_check(header1, commit_data.node, z, pcomp, commit_data.rotations);
0599 rebalance_for_erasure(header2, z, pcomp);
0600 bstree_algo::erase(header2, z);
0601 bstree_algo::insert_unique_commit(header1, z, commit_data);
0602 rotate_up_n(header1, z, commit_data.rotations);
0603 }
0604
0605 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0606
0607
0608 static bool is_header(const_node_ptr p) BOOST_NOEXCEPT;
0609 #endif
0610
0611
0612 private:
0613
0614 template<class NodePtrPriorityCompare>
0615 static void rebalance_for_erasure(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp)
0616 {
0617 std::size_t n = 0;
0618 rerotate_on_destroy rb(header, z, n);
0619
0620 node_ptr z_left = NodeTraits::get_left(z);
0621 node_ptr z_right = NodeTraits::get_right(z);
0622 while(z_left || z_right){
0623 const node_ptr z_parent(NodeTraits::get_parent(z));
0624 if(!z_right || (z_left && pcomp(z_left, z_right))){
0625 bstree_algo::rotate_right(z, z_left, z_parent, header);
0626 }
0627 else{
0628 bstree_algo::rotate_left(z, z_right, z_parent, header);
0629 }
0630 ++n;
0631 z_left = NodeTraits::get_left(z);
0632 z_right = NodeTraits::get_right(z);
0633 }
0634 rb.release();
0635 }
0636
0637 template<class NodePtrPriorityCompare>
0638 static void rebalance_check_and_commit
0639 (node_ptr h, node_ptr new_node, NodePtrPriorityCompare pcomp, insert_commit_data &commit_data)
0640 {
0641 rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations);
0642
0643 bstree_algo::insert_unique_commit(h, new_node, commit_data);
0644 rotate_up_n(h, new_node, commit_data.rotations);
0645 }
0646
0647 template<class Key, class KeyNodePriorityCompare>
0648 static void rebalance_after_insertion_check
0649 (const_node_ptr header, const_node_ptr up, const Key &k
0650 , KeyNodePriorityCompare pcomp, std::size_t &num_rotations)
0651 {
0652 const_node_ptr upnode(up);
0653
0654 num_rotations = 0;
0655 std::size_t n = 0;
0656 while(upnode != header && pcomp(k, upnode)){
0657 ++n;
0658 upnode = NodeTraits::get_parent(upnode);
0659 }
0660 num_rotations = n;
0661 }
0662
0663 template<class NodePtrPriorityCompare>
0664 static bool check_invariant(const_node_ptr header, NodePtrPriorityCompare pcomp)
0665 {
0666 node_ptr beg = begin_node(header);
0667 node_ptr end = end_node(header);
0668
0669 while(beg != end){
0670 node_ptr p = NodeTraits::get_parent(beg);
0671 if(p != header){
0672 if(pcomp(beg, p))
0673 return false;
0674 }
0675 beg = next_node(beg);
0676 }
0677 return true;
0678 }
0679
0680
0681 };
0682
0683
0684
0685 template<class NodeTraits>
0686 struct get_algo<TreapAlgorithms, NodeTraits>
0687 {
0688 typedef treap_algorithms<NodeTraits> type;
0689 };
0690
0691 template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
0692 struct get_node_checker<TreapAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
0693 {
0694 typedef detail::bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
0695 };
0696
0697
0698
0699 }
0700 }
0701
0702 #include <boost/intrusive/detail/config_end.hpp>
0703
0704 #endif