From 3c6f96a96a951fe46f13c681f14436ce21c9ef9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 19 Jan 2014 14:28:57 +0100 Subject: [PATCH] Improved "count" for unique associative containers. Instead of calling tree's count just use find() != end() to avoid iterations as there is only one potential key. Fixed some typos. --- doc/intrusive.qbk | 5 +- include/boost/intrusive/avl_set.hpp | 14 +- include/boost/intrusive/avltree.hpp | 2 +- .../boost/intrusive/avltree_algorithms.hpp | 1 + include/boost/intrusive/bs_set.hpp | 12 +- include/boost/intrusive/bstree.hpp | 70 ++-- include/boost/intrusive/bstree_algorithms.hpp | 10 +- include/boost/intrusive/detail/mpl.hpp | 6 + include/boost/intrusive/rbtree.hpp | 2 +- include/boost/intrusive/rbtree_algorithms.hpp | 1 + include/boost/intrusive/set.hpp | 14 +- include/boost/intrusive/sg_set.hpp | 12 +- include/boost/intrusive/sgtree.hpp | 27 +- include/boost/intrusive/sgtree_algorithms.hpp | 31 +- include/boost/intrusive/splay_set.hpp | 111 +----- include/boost/intrusive/splaytree.hpp | 90 +---- .../boost/intrusive/splaytree_algorithms.hpp | 315 +++++++++--------- include/boost/intrusive/treap.hpp | 2 +- include/boost/intrusive/treap_algorithms.hpp | 1 + include/boost/intrusive/treap_set.hpp | 12 +- test/test_container.hpp | 2 +- 21 files changed, 324 insertions(+), 416 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index aca3694..adc047b 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3788,8 +3788,9 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * Improved Doxygen generated reference and updated and fixed forward-declaration header. -* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers and - removed `splay_set_base_hook` and `splay_set_member_hook`from splay containers. +* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers, + `splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true` + extra parameter is `splaytree_algorithms` functions. * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]]. diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 061a086..b70fd89 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -249,13 +249,19 @@ class avl_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -692,7 +698,7 @@ class avl_multiset_impl //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index 225efcc..e87de01 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -296,7 +296,7 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 54f9fe0..31777d7 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -274,6 +274,7 @@ class avltree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp index 2062d49..ce3c490 100644 --- a/include/boost/intrusive/bs_set.hpp +++ b/include/boost/intrusive/bs_set.hpp @@ -247,13 +247,19 @@ class bs_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) == this->tree_type::cend()); } //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) == this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 144415d..c880731 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -431,6 +431,16 @@ struct bstbase const size_traits &sz_traits() const { return *this; } + bool empty() const + { + if(ConstantTimeSize){ + return !this->sz_traits().get_size(); + } + else{ + return algo_type::unique(this->header_ptr()); + } + } + size_type count(const_reference value) const { return size_type(this->count(value, this->comp())); } @@ -441,14 +451,16 @@ struct bstbase return size_type(std::distance(ret.first, ret.second)); } - bool empty() const + //Add non-const overloads to theoretically const members + //as some algorithms have different behavior when non-const versions are used (like splay trees). + size_type count(const_reference value) + { return size_type(this->count(value, this->comp())); } + + template + size_type count(const KeyType &key, KeyValueCompare comp) { - if(ConstantTimeSize){ - return !this->sz_traits().get_size(); - } - else{ - return algo_type::unique(this->header_ptr()); - } + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); } }; @@ -1364,7 +1376,7 @@ class bstree_impl //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given value. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. size_type count(const_reference value) const; //! Effects: Returns the number of contained elements with the given key @@ -1372,7 +1384,7 @@ class bstree_impl //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given key. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template size_type count(const KeyType &key, KeyValueCompare comp) const; @@ -1381,7 +1393,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. iterator lower_bound(const_reference value); //! Effects: Returns an iterator to the first element whose @@ -1389,7 +1401,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. const_iterator lower_bound(const_reference value) const; //! Effects: Returns an iterator to the first element whose @@ -1397,7 +1409,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template iterator lower_bound(const KeyType &key, KeyValueCompare comp); @@ -1406,7 +1418,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; @@ -1415,7 +1427,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. iterator upper_bound(const_reference value); //! Effects: Returns an iterator to the first element whose @@ -1424,7 +1436,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template iterator upper_bound(const KeyType &key, KeyValueCompare comp); @@ -1433,7 +1445,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. const_iterator upper_bound(const_reference value) const; //! Effects: Returns an iterator to the first element whose @@ -1442,7 +1454,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; @@ -1451,7 +1463,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. iterator find(const_reference value); //! Effects: Finds an iterator to the first element whose key is @@ -1459,7 +1471,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template iterator find(const KeyType &key, KeyValueCompare comp); @@ -1468,7 +1480,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. const_iterator find(const_reference value) const; //! Effects: Finds a const_iterator to the first element whose key is @@ -1476,7 +1488,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template const_iterator find(const KeyType &key, KeyValueCompare comp) const; @@ -1486,7 +1498,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. std::pair equal_range(const_reference value); //! Effects: Finds a range containing all elements whose key is k or @@ -1495,7 +1507,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template std::pair equal_range(const KeyType &key, KeyValueCompare comp); @@ -1505,7 +1517,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. std::pair equal_range(const_reference value) const; @@ -1515,7 +1527,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template std::pair equal_range(const KeyType &key, KeyValueCompare comp) const; @@ -1531,7 +1543,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If the predicate throws. + //! Throws: If `value_compare` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_value and upper_value. @@ -1554,7 +1566,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If "comp" throws. + //! Throws: If `comp` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_key and upper_key. @@ -1575,7 +1587,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If the predicate throws. + //! Throws: If `value_compare` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_value and upper_value. @@ -1598,7 +1610,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If "comp" throws. + //! Throws: If `comp` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_key and upper_key. diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 1766e0d..b94310b 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -173,7 +173,7 @@ class bstree_algorithms static node_ptr end_node(const const_node_ptr & header) { return detail::uncast(header); } - //! Requires: 'node' is a node of the tree or an node initialized + //! Requires: 'node' is a node of the tree or a node initialized //! by init(...) or init_node. //! //! Effects: Returns true if the node is initialized by init() or init_node(). @@ -766,7 +766,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the element that is equivalent to + //! Effects: Returns a node_ptr to the first element that is equivalent to //! "key" according to "comp" or "header" if that element does not exist. //! //! Complexity: Logarithmic. @@ -863,7 +863,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns the number of elements with a key equivalent to "key"pair of node_ptr delimiting a range containing + //! Effects: Returns the number of elements with a key equivalent to "key" //! according to "comp". //! //! Complexity: Logarithmic. @@ -907,7 +907,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the first element that is + //! Effects: Returns a node_ptr to the first element that is //! not less than "key" according to "comp" or "header" if that element does //! not exist. //! @@ -926,7 +926,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the first element that is greater + //! Effects: Returns a node_ptr to the first element that is greater //! than "key" according to "comp" or "header" if that element does not exist. //! //! Complexity: Logarithmic. diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 6f99d7c..4358aec 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -29,6 +29,12 @@ struct bool_ static const bool value = C_; }; +template< class Integer, Integer Value > +struct integer +{ + static const Integer value = Value; +}; + typedef bool_ true_; typedef bool_ false_; diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 326b13f..bff85de 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -292,7 +292,7 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index e20b4d8..457df31 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -297,6 +297,7 @@ class rbtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 208360d..43673e3 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -249,13 +249,19 @@ class set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -692,7 +698,7 @@ class multiset_impl //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 7e5d072..11545ab 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -247,13 +247,19 @@ class sg_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 5b42185..b28b0ae 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -48,6 +48,12 @@ namespace intrusive { namespace detail{ +///////////////////////////////////////////////////////////// +// +// Halpha for fixed floating_point option +// +///////////////////////////////////////////////////////////// + //! Returns floor(log2(n)/log2(sqrt(2))) -> floor(2*log2(n)) //! Undefined if N is 0. //! @@ -55,7 +61,7 @@ namespace detail{ inline std::size_t calculate_h_sqrt2 (std::size_t n) { std::size_t f_log2 = detail::floor_log2(n); - return (2*f_log2) + (n >= detail::sqrt2_pow_2xplus1 (f_log2)); + return (2*f_log2) + static_cast(n >= detail::sqrt2_pow_2xplus1(f_log2)); } struct h_alpha_sqrt2_t @@ -76,6 +82,12 @@ struct alpha_0_75_by_max_size_t } }; +///////////////////////////////////////////////////////////// +// +// Halpha for fixed floating_point option +// +///////////////////////////////////////////////////////////// + struct h_alpha_t { explicit h_alpha_t(float inv_minus_logalpha) @@ -84,9 +96,12 @@ struct h_alpha_t std::size_t operator()(std::size_t n) const { - //Returns floor(log2(1/alpha(n))) -> - // floor(log2(n)/log(1/alpha)) -> - // floor(log2(n)/(-log2(alpha))) + //////////////////////////////////////////////////////////// + // This function must return "floor(log2(1/alpha(n)))" -> + // floor(log2(n)/log(1/alpha)) -> + // floor(log2(n)/-log2(alpha)) + // floor(log2(n)*(1/-log2(alpha))) + //////////////////////////////////////////////////////////// //return static_cast(std::log(float(n))*inv_minus_logalpha_); return static_cast(detail::fast_log2(float(n))*inv_minus_logalpha_); } @@ -119,7 +134,7 @@ struct alpha_holder typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t; alpha_holder() : max_tree_size_(0) - { set_alpha(0.7f); } + { set_alpha(0.70711f); } // ~1/sqrt(2) float get_alpha() const { return alpha_; } @@ -666,7 +681,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index 65a76b1..2e4ce28 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -187,6 +187,7 @@ class sgtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) @@ -330,25 +331,21 @@ class sgtree_algorithms //than the weight balanced method. node_ptr s = x; std::size_t size = 1; - for(std::size_t ancestor = 1; true; ++ancestor){ - if(ancestor == depth){ //Check if whole tree must be rebuilt - max_tree_size = tree_size; - bstree_algo::rebalance_subtree(NodeTraits::get_parent(s)); - break; - } - else{ //Go to the next scapegoat candidate - const node_ptr s_parent = NodeTraits::get_parent(s); - const node_ptr s_parent_left = NodeTraits::get_left(s_parent); - //Obtain parent's size (previous size + parent + sibling tree) - const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left; - size += 1 + bstree_algo::subtree_size(s_sibling); - s = s_parent; - if(ancestor > h_alpha(size)){ //is 's' scapegoat? - bstree_algo::rebalance_subtree(s); - break; - } + for(std::size_t ancestor = 1; ancestor != depth; ++ancestor){ + const node_ptr s_parent = NodeTraits::get_parent(s); + const node_ptr s_parent_left = NodeTraits::get_left(s_parent); + //Obtain parent's size (previous size + parent + sibling tree) + const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left; + size += 1 + bstree_algo::subtree_size(s_sibling); + s = s_parent; + if(ancestor > h_alpha(size)){ //is 's' scapegoat? + bstree_algo::rebalance_subtree(s); + return; } } + //The whole tree must be rebuilt + max_tree_size = tree_size; + bstree_algo::rebalance_subtree(NodeTraits::get_parent(s)); } } /// @endcond diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 0a80ce6..97654fc 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -247,12 +247,18 @@ class splay_set_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference) - size_type count(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp); + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const size_type count(const_reference value) const; @@ -261,13 +267,6 @@ class splay_set_impl template size_type count(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const - size_type count_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const - template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -282,13 +281,6 @@ class splay_set_impl template const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const - const_iterator lower_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) iterator upper_bound(const_reference value); @@ -303,13 +295,6 @@ class splay_set_impl template const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const - const_iterator upper_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) iterator find(const_reference value); @@ -324,13 +309,6 @@ class splay_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const - const_iterator find_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) std::pair equal_range(const_reference value); @@ -347,15 +325,6 @@ class splay_set_impl std::pair equal_range(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const - std::pair - equal_range_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const - template - std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -374,15 +343,6 @@ class splay_set_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -760,20 +720,6 @@ class splay_multiset_impl template size_type count(const KeyType& key, KeyValueCompare comp); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const - size_type count(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const - size_type count_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const - template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -788,13 +734,6 @@ class splay_multiset_impl template const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const - const_iterator lower_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) iterator upper_bound(const_reference value); @@ -809,13 +748,6 @@ class splay_multiset_impl template const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const - const_iterator upper_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) iterator find(const_reference value); @@ -830,13 +762,6 @@ class splay_multiset_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const - const_iterator find_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) std::pair equal_range(const_reference value); @@ -853,15 +778,6 @@ class splay_multiset_impl std::pair equal_range(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const - std::pair - equal_range_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const - template - std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -880,15 +796,6 @@ class splay_multiset_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index b0e4469..d754f5a 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -266,7 +266,6 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) @@ -292,60 +291,32 @@ class splaytree_impl template void clear_and_dispose(Disposer disposer); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "value" - size_type count(const_reference value) - { return this->count(value, this->value_comp()); } + //! Additional note: non-const function, splaying is performed. + size_type count(const_reference value); //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "key" + //! Additional note: non-const function, splaying is performed. template - size_type count(const KeyType &key, KeyValueCompare comp) - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } + size_type count(const KeyType &key, KeyValueCompare comp); //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: Deprecated function, use count const overload instead. - size_type count(const_reference value) const - { return tree_type::count(value); } + //! Additional note: const function, no splaying is performed + size_type count(const_reference value) const; //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use count const overload instead. + //! Additional note: const function, no splaying is performed template - size_type count(const KeyType &key, KeyValueCompare comp) const - { return tree_type::count(key, comp); } + size_type count(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: Deprecated function, use count const overload instead. - size_type count_dont_splay(const_reference value) const - { return tree_type::count(value); } - - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use count const overload instead. - template - size_type count_dont_splay(const KeyType &key, KeyValueCompare comp) const - { return tree_type::count(key, comp); } - - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "value" + //! Additional note: non-const function, splaying is performed. iterator lower_bound(const_reference value); //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const //! Additional note: const function, no splaying is performed const_iterator lower_bound(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - //! Additional note: Deprecated function, use lower_bound const overload instead. - const_iterator lower_bound_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -357,11 +328,6 @@ class splaytree_impl template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use lower_bound const overload instead. - template - iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -371,10 +337,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed const_iterator upper_bound(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - //! Additional note: Deprecated function, use upper_bound const overload instead. - const_iterator upper_bound_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -386,11 +348,6 @@ class splaytree_impl template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use upper_bound const overload instead. - template - const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -400,10 +357,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed const_iterator find(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - //! Additional note: Deprecated function, use find const overload instead. - const_iterator find_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -415,11 +368,6 @@ class splaytree_impl template const_iterator find(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use find const overload instead. - template - const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -429,10 +377,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed std::pair equal_range(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const - //! Additional note: Deprecated function, use equal_range const overload instead. - std::pair equal_range_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -444,11 +388,6 @@ class splaytree_impl template std::pair equal_range(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use equal_range const overload instead. - template - std::pair equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -467,17 +406,6 @@ class splaytree_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const - //! Additional note: Deprecated function, use bounded_range const overload instead. - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - //! Additional note: Deprecated function, use bounded_range const overload instead. - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 3627b8c..32130e6 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -45,33 +45,70 @@ namespace intrusive { namespace detail { template -struct splaydown_rollback +struct splaydown_assemble_and_fix_header { typedef typename NodeTraits::node_ptr node_ptr; - splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header - , const node_ptr & leftmost , const node_ptr & rightmost) - : pcur_subtree_(pcur_subtree) , header_(header) - , leftmost_(leftmost) , rightmost_(rightmost) + + splaydown_assemble_and_fix_header(const node_ptr & t, const node_ptr & header, const node_ptr &leftmost, const node_ptr &rightmost) + : t_(t) + , null_node_(header) + , l_(null_node_) + , r_(null_node_) + , leftmost_(leftmost) + , rightmost_(rightmost) {} - void release() - { pcur_subtree_ = 0; } - - ~splaydown_rollback() + ~splaydown_assemble_and_fix_header() { - if(pcur_subtree_){ - //Exception can only be thrown by comp, but - //tree invariants still hold. *pcur_subtree is the current root - //so link it to the header. - NodeTraits::set_parent(*pcur_subtree_, header_); - NodeTraits::set_parent(header_, *pcur_subtree_); - //Recover leftmost/rightmost pointers - NodeTraits::set_left (header_, leftmost_); - NodeTraits::set_right(header_, rightmost_); + this->assemble(); + + //Now recover the original header except for the + //splayed root node. + //"t_" is the current root and "null_node_" is the header node + NodeTraits::set_parent(null_node_, t_); + NodeTraits::set_parent(t_, null_node_); + //Recover leftmost/rightmost pointers + NodeTraits::set_left (null_node_, leftmost_); + NodeTraits::set_right(null_node_, rightmost_); + } + + private: + + void assemble() + { + //procedure assemble; + // left(r), right(l) := right(t), left(t); + // left(t), right(t) := right(null), left(null); + //end assemble; + { // left(r), right(l) := right(t), left(t); + + node_ptr const old_t_left = NodeTraits::get_left(t_); + node_ptr const old_t_right = NodeTraits::get_right(t_); + NodeTraits::set_right(l_, old_t_left); + NodeTraits::set_left (r_, old_t_right); + if(old_t_left){ + NodeTraits::set_parent(old_t_left, l_); + } + if(old_t_right){ + NodeTraits::set_parent(old_t_right, r_); + } + } + { // left(t), right(t) := right(null), left(null); + node_ptr const null_right = NodeTraits::get_right(null_node_); + node_ptr const null_left = NodeTraits::get_left(null_node_); + NodeTraits::set_left (t_, null_right); + NodeTraits::set_right(t_, null_left); + if(null_right){ + NodeTraits::set_parent(null_right, t_); + } + if(null_left){ + NodeTraits::set_parent(null_left, t_); + } } } - const node_ptr *pcur_subtree_; - node_ptr header_, leftmost_, rightmost_; + + public: + node_ptr t_, null_node_, l_, r_, leftmost_, rightmost_; }; } //namespace detail { @@ -184,32 +221,28 @@ class splaytree_algorithms #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) - //! Additional notes: the previous node of z is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. - static void erase(const node_ptr & header, const node_ptr & z, bool splay = true) + //! Additional notes: the previous node of z is splayed to speed up range deletions. + static void erase(const node_ptr & header, const node_ptr & z) { //posibility 1 - if(splay && NodeTraits::get_left(z)){ + if(NodeTraits::get_left(z)){ splay_up(bstree_algo::prev_node(z), header); } /* //possibility 2 - if(splay && NodeTraits::get_left(z)){ + if(NodeTraits::get_left(z)){ node_ptr l = NodeTraits::get_left(z); splay_up(l, header); - }*//* - if(splay && NodeTraits::get_left(z)){ + }*/ + /* + if(NodeTraits::get_left(z)){ node_ptr l = bstree_algo::prev_node(z); splay_up_impl(l, z); }*/ /* //possibility 4 - if(splay){ - splay_up(z, header); - }*/ - - //if(splay) - //splay_up(z, header); + splay_up(z, header); + */ bstree_algo::erase(header, z); } @@ -225,7 +258,7 @@ class splaytree_algorithms #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. + //! Additional notes: an element with key `key` is splayed. template static std::size_t count (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) @@ -247,15 +280,14 @@ class splaytree_algorithms { return bstree_algo::count(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static node_ptr lower_bound - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); node_ptr y = bstree_algo::lower_bound(header, key, comp); - if(splay) splay_up(y, detail::uncast(header)); + //splay_up(y, detail::uncast(header)); return y; } @@ -267,15 +299,14 @@ class splaytree_algorithms { return bstree_algo::lower_bound(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static node_ptr upper_bound - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); node_ptr y = bstree_algo::upper_bound(header, key, comp); - if(splay) splay_up(y, detail::uncast(header)); + //splay_up(y, detail::uncast(header)); return y; } @@ -287,17 +318,13 @@ class splaytree_algorithms { return bstree_algo::upper_bound(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) - //! Additional notes: the found node of the lower bound is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the found node of the lower bound is splayed. template static node_ptr find - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - if(splay) splay_down(detail::uncast(header), key, comp); - node_ptr end = detail::uncast(header); - node_ptr y = bstree_algo::lower_bound(header, key, comp); - node_ptr r = (y == end || comp(key, y)) ? end : y; - return r; + splay_down(detail::uncast(header), key, comp); + return bstree_algo::find(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) @@ -308,15 +335,14 @@ class splaytree_algorithms { return bstree_algo::find(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static std::pair equal_range - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); std::pair ret = bstree_algo::equal_range(header, key, comp); - if(splay) splay_up(ret.first, detail::uncast(header)); + //splay_up(ret.first, detail::uncast(header)); return ret; } @@ -328,16 +354,16 @@ class splaytree_algorithms { return bstree_algo::equal_range(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static std::pair bounded_range (const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed, bool splay = true) + , bool left_closed, bool right_closed) { + splay_down(detail::uncast(header), lower_key, comp); std::pair ret = bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); - if(splay) splay_up(ret.first, detail::uncast(header)); + //splay_up(ret.first, detail::uncast(header)); return ret; } @@ -445,6 +471,20 @@ class splaytree_algorithms // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow static void splay_up(const node_ptr & node, const node_ptr & header) + { priv_splay_up(node, header); } + + // top-down splay | complexity : logarithmic | exception : strong, note A + template + static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) + { return priv_splay_down(header, key, comp, pfound); } + + private: + + /// @cond + + // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow + template + static void priv_splay_up(const node_ptr & node, const node_ptr & header) { // If (node == header) do a splay for the right most node instead // this is to boost performance of equal_range/count on equivalent containers in the case @@ -470,20 +510,19 @@ class splaytree_algorithms rotate(p); rotate(n); } - else{ + else { // zig-zag rotate(n); - rotate(n); + if(!SimpleSplay){ + rotate(n); + } } } } - // top-down splay | complexity : logarithmic | exception : strong, note A - template - static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + template + static node_ptr priv_splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) { - if(!NodeTraits::get_parent(header)) - return header; //Most splay tree implementations use a dummy/null node to implement. //this function. This has some problems for a generic library like Intrusive: // @@ -494,123 +533,87 @@ class splaytree_algorithms //are not changed when splaying (because the invariants of the tree don't //change) We can back up them, use the header as the null node and //reassign old values after the function has been completed. - node_ptr t = NodeTraits::get_parent(header); - //Check if tree has a single node - if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) - return t; - //Backup leftmost/rightmost - node_ptr leftmost (NodeTraits::get_left(header)); - node_ptr rightmost(NodeTraits::get_right(header)); - { - //Anti-exception rollback, recovers the original header node if an exception is thrown. - detail::splaydown_rollback rollback(&t, header, leftmost, rightmost); - node_ptr null_node = header; - node_ptr l = null_node; - node_ptr r = null_node; + node_ptr const old_root = NodeTraits::get_parent(header); + node_ptr const leftmost = NodeTraits::get_left(header); + node_ptr const rightmost = NodeTraits::get_right(header); + if(leftmost == rightmost){ //Empty or unique node + if(pfound){ + *pfound = old_root && !comp(key, old_root) && !comp(old_root, key); + } + return old_root ? old_root : header; + } + else{ + //Initialize "null node" (the header in our case) + NodeTraits::set_left (header, node_ptr()); + NodeTraits::set_right(header, node_ptr()); + //Class that will backup leftmost/rightmost from header, commit the assemble(), + //and will restore leftmost/rightmost to header even if "comp" throws + detail::splaydown_assemble_and_fix_header commit(old_root, header, leftmost, rightmost); + bool found = false; for( ;; ){ - if(comp(key, t)){ - node_ptr const t_left = NodeTraits::get_left(t); + if(comp(key, commit.t_)){ + node_ptr const t_left = NodeTraits::get_left(commit.t_); if(!t_left) break; if(comp(key, t_left)){ - t = bstree_algo::rotate_right(t); + commit.t_ = bstree_algo::rotate_right(commit.t_); - if( !NodeTraits::get_left(t) ) + if( !NodeTraits::get_left(commit.t_) ) break; - link_right(t, r); - } - else if(comp(t_left, key)){ - link_right(t, r); - - if( !NodeTraits::get_right(t) ) - break; - link_left(t, l); + link_right(commit.t_, commit.r_); } else{ - link_right(t, r); + link_right(commit.t_, commit.r_); + if(!SimpleSplay && comp(t_left, key)){ + if( !NodeTraits::get_right(commit.t_) ) + break; + link_left(commit.t_, commit.l_); + } } } - else if(comp(t, key)){ - node_ptr const t_right = NodeTraits::get_right(t); + else if(comp(commit.t_, key)){ + node_ptr const t_right = NodeTraits::get_right(commit.t_); if(!t_right) break; if(comp(t_right, key)){ - t = bstree_algo::rotate_left( t ); + commit.t_ = bstree_algo::rotate_left( commit.t_ ); - if( !NodeTraits::get_right(t) ) + if( !NodeTraits::get_right(commit.t_) ) break; - link_left(t, l); - } - else if(comp(key, t_right)){ - link_left(t, l); - - if( !NodeTraits::get_left(t) ) - break; - - link_right(t, r); + link_left(commit.t_, commit.l_); } else{ - link_left(t, l); + link_left(commit.t_, commit.l_); + if(!SimpleSplay && comp(key, t_right)){ + if( !NodeTraits::get_left(commit.t_) ) + break; + link_right(commit.t_, commit.r_); + } } } else{ + found = true; break; } } - assemble(t, l, r, null_node); - rollback.release(); - } - - //Now recover the original header except for the - //splayed root node. - //t is the current root - NodeTraits::set_parent(header, t); - NodeTraits::set_parent(t, header); - //Recover leftmost/rightmost pointers - NodeTraits::set_left (header, leftmost); - NodeTraits::set_right(header, rightmost); - return t; - } - - private: - - /// @cond - - // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow - static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node ) - { - node_ptr const new_l_right = NodeTraits::get_left(t); - node_ptr const new_r_left = NodeTraits::get_right(t); - NodeTraits::set_right(l, new_l_right); - NodeTraits::set_left (r, new_r_left); - - if(new_l_right){ - NodeTraits::set_parent(new_l_right, l); - } - if(new_r_left){ - NodeTraits::set_parent(new_r_left, r); - } - - node_ptr const t_new_left = NodeTraits::get_right(null_node); - node_ptr const t_new_right = NodeTraits::get_left(null_node); - NodeTraits::set_left (t, t_new_left); - NodeTraits::set_right(t, t_new_right); - - if(t_new_left){ - NodeTraits::set_parent(t_new_left, t); - } - - if(t_new_right){ - NodeTraits::set_parent(t_new_right, t); + //commit.~splaydown_assemble_and_fix_header() will first + //"assemble()" + link the new root & recover header's leftmost & rightmost + if(pfound){ + *pfound = found; + } + return commit.t_; } } // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow static void link_left(node_ptr & t, node_ptr & l) { + //procedure link_left; + // t, l, right(l) := right(t), t, t + //end link_left NodeTraits::set_right(l, t); NodeTraits::set_parent(t, l); l = t; @@ -620,6 +623,9 @@ class splaytree_algorithms // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow static void link_right(node_ptr & t, node_ptr & r) { + //procedure link_right; + // t, r, left(r) := left(t), t, t + //end link_right; NodeTraits::set_left(r, t); NodeTraits::set_parent(t, r); r = t; @@ -629,6 +635,9 @@ class splaytree_algorithms // rotate n with its parent | complexity : constant | exception : nothrow static void rotate(const node_ptr & n) { + //procedure rotate_left; + // t, right(t), left(right(t)) := right(t), left(right(t)), t + //end rotate_left; node_ptr p = NodeTraits::get_parent(n); node_ptr g = NodeTraits::get_parent(p); //Test if g is header before breaking tree diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index eb0e501..e3ced65 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -910,7 +910,7 @@ class treap_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 6a61b7e..e7d887a 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -248,6 +248,7 @@ class treap_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: "h" must be the header node of a tree. diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 739e56b..cb59a72 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -291,13 +291,19 @@ class treap_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/test/test_container.hpp b/test/test_container.hpp index bb6444d..47ac9e6 100644 --- a/test/test_container.hpp +++ b/test/test_container.hpp @@ -219,7 +219,7 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo c.erase(*da, c.key_comp()); BOOST_TEST( c.size() == old_size-1 ); - //This should not eras anyone + //This should not erase any size_type second_erase = c.erase_and_dispose( *da, c.key_comp(), detail::null_disposer() ); BOOST_TEST( second_erase == 0 );