File indexing completed on 2025-01-18 09:38:46
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 std::size_t rotations;
0176
0177 };
0178
0179 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0180
0181
0182 static node_ptr get_header(const_node_ptr n) BOOST_NOEXCEPT;
0183
0184
0185 static node_ptr begin_node(const_node_ptr header) BOOST_NOEXCEPT;
0186
0187
0188 static node_ptr end_node(const_node_ptr header) BOOST_NOEXCEPT;
0189
0190
0191 static void swap_tree(node_ptr header1, node_ptr header2) BOOST_NOEXCEPT;
0192
0193
0194 static void swap_nodes(node_ptr node1, node_ptr node2) BOOST_NOEXCEPT;
0195
0196
0197 static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) BOOST_NOEXCEPT;
0198
0199
0200 static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) BOOST_NOEXCEPT;
0201
0202
0203 static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) BOOST_NOEXCEPT;
0204 #endif
0205
0206
0207 template<class NodePtrPriorityCompare>
0208 static void unlink(node_ptr n, NodePtrPriorityCompare pcomp)
0209 {
0210 node_ptr x = NodeTraits::get_parent(n);
0211 if(x){
0212 while(!bstree_algo::is_header(x))
0213 x = NodeTraits::get_parent(x);
0214 erase(x, n, pcomp);
0215 }
0216 }
0217
0218 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0219
0220 static node_ptr unlink_leftmost_without_rebalance(node_ptr header) BOOST_NOEXCEPT;
0221
0222
0223 static bool unique(const_node_ptr n) BOOST_NOEXCEPT;
0224
0225
0226 static std::size_t size(const_node_ptr header) BOOST_NOEXCEPT;
0227
0228
0229 static node_ptr next_node(node_ptr n) BOOST_NOEXCEPT;
0230
0231
0232 static node_ptr prev_node(node_ptr n) BOOST_NOEXCEPT;
0233
0234
0235 static void init(node_ptr n) BOOST_NOEXCEPT;
0236
0237
0238 static void init_header(node_ptr header) BOOST_NOEXCEPT;
0239 #endif
0240
0241
0242 template<class NodePtrPriorityCompare>
0243 static node_ptr erase(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp)
0244 {
0245 rebalance_for_erasure(header, z, pcomp);
0246 bstree_algo::erase(header, z);
0247 return z;
0248 }
0249
0250 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0251
0252 template <class Cloner, class Disposer>
0253 static void clone
0254 (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer);
0255
0256
0257 template<class Disposer>
0258 static void clear_and_dispose(node_ptr header, Disposer disposer) BOOST_NOEXCEPT;
0259
0260
0261 template<class KeyType, class KeyNodePtrCompare>
0262 static node_ptr lower_bound
0263 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0264
0265
0266 template<class KeyType, class KeyNodePtrCompare>
0267 static node_ptr upper_bound
0268 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0269
0270
0271 template<class KeyType, class KeyNodePtrCompare>
0272 static node_ptr find
0273 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0274
0275
0276 template<class KeyType, class KeyNodePtrCompare>
0277 static std::pair<node_ptr, node_ptr> equal_range
0278 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0279
0280
0281 template<class KeyType, class KeyNodePtrCompare>
0282 static std::pair<node_ptr, node_ptr> bounded_range
0283 (const_node_ptr header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
0284 , bool left_closed, bool right_closed);
0285
0286
0287 template<class KeyType, class KeyNodePtrCompare>
0288 static std::size_t count(const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0289
0290 #endif
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 template<class NodePtrCompare, class NodePtrPriorityCompare>
0308 static node_ptr insert_equal_upper_bound
0309 (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp)
0310 {
0311 insert_commit_data commit_data;
0312 bstree_algo::insert_equal_upper_bound_check(h, new_node, comp, commit_data);
0313 rebalance_check_and_commit(h, new_node, pcomp, commit_data);
0314 return new_node;
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 template<class NodePtrCompare, class NodePtrPriorityCompare>
0333 static node_ptr insert_equal_lower_bound
0334 (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp)
0335 {
0336 insert_commit_data commit_data;
0337 bstree_algo::insert_equal_lower_bound_check(h, new_node, comp, commit_data);
0338 rebalance_check_and_commit(h, new_node, pcomp, commit_data);
0339 return new_node;
0340 }
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360 template<class NodePtrCompare, class NodePtrPriorityCompare>
0361 static node_ptr insert_equal
0362 (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp)
0363 {
0364 insert_commit_data commit_data;
0365 bstree_algo::insert_equal_check(h, hint, new_node, comp, commit_data);
0366 rebalance_check_and_commit(h, new_node, pcomp, commit_data);
0367 return new_node;
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388 template<class NodePtrPriorityCompare>
0389 static node_ptr insert_before
0390 (node_ptr header, node_ptr pos, node_ptr new_node, NodePtrPriorityCompare pcomp)
0391 {
0392 insert_commit_data commit_data;
0393 bstree_algo::insert_before_check(header, pos, commit_data);
0394 rebalance_check_and_commit(header, new_node, pcomp, commit_data);
0395 return new_node;
0396 }
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415 template<class NodePtrPriorityCompare>
0416 static void push_back(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp)
0417 {
0418 insert_commit_data commit_data;
0419 bstree_algo::push_back_check(header, commit_data);
0420 rebalance_check_and_commit(header, new_node, pcomp, commit_data);
0421 }
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 template<class NodePtrPriorityCompare>
0441 static void push_front(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp)
0442 {
0443 insert_commit_data commit_data;
0444 bstree_algo::push_front_check(header, commit_data);
0445 rebalance_check_and_commit(header, new_node, pcomp, commit_data);
0446 }
0447
0448
0449
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 template<class KeyType, class KeyNodePtrCompare, class PrioType, class PrioNodePtrPrioCompare>
0483 static std::pair<node_ptr, bool> insert_unique_check
0484 ( const_node_ptr header
0485 , const KeyType &key, KeyNodePtrCompare comp
0486 , const PrioType &prio, PrioNodePtrPrioCompare pcomp
0487 , insert_commit_data &commit_data)
0488 {
0489 std::pair<node_ptr, bool> ret =
0490 bstree_algo::insert_unique_check(header, key, comp, commit_data);
0491 if(ret.second)
0492 rebalance_after_insertion_check(header, commit_data.node, prio, pcomp, commit_data.rotations);
0493 return ret;
0494 }
0495
0496
0497
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 template<class KeyType, class KeyNodePtrCompare, class PrioType, class PrioNodePtrPrioCompare>
0536 static std::pair<node_ptr, bool> insert_unique_check
0537 ( const_node_ptr header, node_ptr hint
0538 , const KeyType &key, KeyNodePtrCompare comp
0539 , const PrioType &prio, PrioNodePtrPrioCompare pcomp
0540 , insert_commit_data &commit_data)
0541 {
0542 std::pair<node_ptr, bool> ret =
0543 bstree_algo::insert_unique_check(header, hint, key, comp, commit_data);
0544 if(ret.second)
0545 rebalance_after_insertion_check(header, commit_data.node, prio, pcomp, commit_data.rotations);
0546 return ret;
0547 }
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566 static void insert_unique_commit
0567 (node_ptr header, node_ptr new_node, const insert_commit_data &commit_data) BOOST_NOEXCEPT
0568 {
0569 bstree_algo::insert_unique_commit(header, new_node, commit_data);
0570 rotate_up_n(header, new_node, commit_data.rotations);
0571 }
0572
0573
0574 template<class NodePtrCompare, class PrioNodePtrPrioCompare>
0575 static bool transfer_unique
0576 (node_ptr header1, NodePtrCompare comp, PrioNodePtrPrioCompare pcomp, node_ptr header2, node_ptr z)
0577 {
0578 insert_commit_data commit_data;
0579 bool const transferable = insert_unique_check(header1, z, comp, z, pcomp, commit_data).second;
0580 if(transferable){
0581 erase(header2, z, pcomp);
0582 insert_unique_commit(header1, z, commit_data);
0583 }
0584 return transferable;
0585 }
0586
0587
0588 template<class NodePtrCompare, class PrioNodePtrPrioCompare>
0589 static void transfer_equal
0590 (node_ptr header1, NodePtrCompare comp, PrioNodePtrPrioCompare pcomp, node_ptr header2, node_ptr z)
0591 {
0592 insert_commit_data commit_data;
0593 bstree_algo::insert_equal_upper_bound_check(header1, z, comp, commit_data);
0594 rebalance_after_insertion_check(header1, commit_data.node, z, pcomp, commit_data.rotations);
0595 rebalance_for_erasure(header2, z, pcomp);
0596 bstree_algo::erase(header2, z);
0597 bstree_algo::insert_unique_commit(header1, z, commit_data);
0598 rotate_up_n(header1, z, commit_data.rotations);
0599 }
0600
0601 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0602
0603
0604 static bool is_header(const_node_ptr p) BOOST_NOEXCEPT;
0605 #endif
0606
0607
0608 private:
0609
0610 template<class NodePtrPriorityCompare>
0611 static void rebalance_for_erasure(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp)
0612 {
0613 std::size_t n = 0;
0614 rerotate_on_destroy rb(header, z, n);
0615
0616 node_ptr z_left = NodeTraits::get_left(z);
0617 node_ptr z_right = NodeTraits::get_right(z);
0618 while(z_left || z_right){
0619 const node_ptr z_parent(NodeTraits::get_parent(z));
0620 if(!z_right || (z_left && pcomp(z_left, z_right))){
0621 bstree_algo::rotate_right(z, z_left, z_parent, header);
0622 }
0623 else{
0624 bstree_algo::rotate_left(z, z_right, z_parent, header);
0625 }
0626 ++n;
0627 z_left = NodeTraits::get_left(z);
0628 z_right = NodeTraits::get_right(z);
0629 }
0630 rb.release();
0631 }
0632
0633 template<class NodePtrPriorityCompare>
0634 static void rebalance_check_and_commit
0635 (node_ptr h, node_ptr new_node, NodePtrPriorityCompare pcomp, insert_commit_data &commit_data)
0636 {
0637 rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations);
0638
0639 bstree_algo::insert_unique_commit(h, new_node, commit_data);
0640 rotate_up_n(h, new_node, commit_data.rotations);
0641 }
0642
0643 template<class Key, class KeyNodePriorityCompare>
0644 static void rebalance_after_insertion_check
0645 (const_node_ptr header, const_node_ptr up, const Key &k
0646 , KeyNodePriorityCompare pcomp, std::size_t &num_rotations)
0647 {
0648 const_node_ptr upnode(up);
0649
0650 num_rotations = 0;
0651 std::size_t n = 0;
0652 while(upnode != header && pcomp(k, upnode)){
0653 ++n;
0654 upnode = NodeTraits::get_parent(upnode);
0655 }
0656 num_rotations = n;
0657 }
0658
0659 template<class NodePtrPriorityCompare>
0660 static bool check_invariant(const_node_ptr header, NodePtrPriorityCompare pcomp)
0661 {
0662 node_ptr beg = begin_node(header);
0663 node_ptr end = end_node(header);
0664
0665 while(beg != end){
0666 node_ptr p = NodeTraits::get_parent(beg);
0667 if(p != header){
0668 if(pcomp(beg, p))
0669 return false;
0670 }
0671 beg = next_node(beg);
0672 }
0673 return true;
0674 }
0675
0676
0677 };
0678
0679
0680
0681 template<class NodeTraits>
0682 struct get_algo<TreapAlgorithms, NodeTraits>
0683 {
0684 typedef treap_algorithms<NodeTraits> type;
0685 };
0686
0687 template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
0688 struct get_node_checker<TreapAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
0689 {
0690 typedef detail::bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
0691 };
0692
0693
0694
0695 }
0696 }
0697
0698 #include <boost/intrusive/detail/config_end.hpp>
0699
0700 #endif