185 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| // (C) Copyright Ion Gaztanaga  2014-2014
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0.
 | |
| //    (See accompanying file LICENSE_1_0.txt or copy at
 | |
| //          http://www.boost.org/LICENSE_1_0.txt)
 | |
| //
 | |
| // See http://www.boost.org/libs/intrusive for documentation.
 | |
| //
 | |
| /////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #ifndef BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP
 | |
| #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP
 | |
| 
 | |
| #ifndef BOOST_CONFIG_HPP
 | |
| #  include <boost/config.hpp>
 | |
| #endif
 | |
| 
 | |
| #if defined(BOOST_HAS_PRAGMA_ONCE)
 | |
| #  pragma once
 | |
| #endif
 | |
| 
 | |
| #include <boost/intrusive/detail/uncast.hpp>
 | |
| 
 | |
| namespace boost {
 | |
| namespace intrusive {
 | |
| 
 | |
| template<class NodeTraits>
 | |
| class bstree_algorithms_base
 | |
| {
 | |
|    public:
 | |
|    typedef typename NodeTraits::node            node;
 | |
|    typedef NodeTraits                           node_traits;
 | |
|    typedef typename NodeTraits::node_ptr        node_ptr;
 | |
|    typedef typename NodeTraits::const_node_ptr  const_node_ptr;
 | |
| 
 | |
|    //! <b>Requires</b>: 'node' is a node from the tree except the header.
 | |
|    //!
 | |
|    //! <b>Effects</b>: Returns the next node of the tree.
 | |
|    //!
 | |
|    //! <b>Complexity</b>: Average constant time.
 | |
|    //!
 | |
|    //! <b>Throws</b>: Nothing.
 | |
|    static node_ptr next_node(const node_ptr & node)
 | |
|    {
 | |
|       node_ptr const n_right(NodeTraits::get_right(node));
 | |
|       if(n_right){
 | |
|          return minimum(n_right);
 | |
|       }
 | |
|       else {
 | |
|          node_ptr n(node);
 | |
|          node_ptr p(NodeTraits::get_parent(n));
 | |
|          while(n == NodeTraits::get_right(p)){
 | |
|             n = p;
 | |
|             p = NodeTraits::get_parent(p);
 | |
|          }
 | |
|          return NodeTraits::get_right(n) != p ? p : n;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    //! <b>Requires</b>: 'node' is a node from the tree except the leftmost node.
 | |
|    //!
 | |
|    //! <b>Effects</b>: Returns the previous node of the tree.
 | |
|    //!
 | |
|    //! <b>Complexity</b>: Average constant time.
 | |
|    //!
 | |
|    //! <b>Throws</b>: Nothing.
 | |
|    static node_ptr prev_node(const node_ptr & node)
 | |
|    {
 | |
|       if(is_header(node)){
 | |
|          //return NodeTraits::get_right(node);
 | |
|          return maximum(NodeTraits::get_parent(node));
 | |
|       }
 | |
|       else if(NodeTraits::get_left(node)){
 | |
|          return maximum(NodeTraits::get_left(node));
 | |
|       }
 | |
|       else {
 | |
|          node_ptr p(node);
 | |
|          node_ptr x = NodeTraits::get_parent(p);
 | |
|          while(p == NodeTraits::get_left(x)){
 | |
|             p = x;
 | |
|             x = NodeTraits::get_parent(x);
 | |
|          }
 | |
|          return x;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    //! <b>Requires</b>: 'node' is a node of a tree but not the header.
 | |
|    //!
 | |
|    //! <b>Effects</b>: Returns the minimum node of the subtree starting at p.
 | |
|    //!
 | |
|    //! <b>Complexity</b>: Logarithmic to the size of the subtree.
 | |
|    //!
 | |
|    //! <b>Throws</b>: Nothing.
 | |
|    static node_ptr minimum(node_ptr node)
 | |
|    {
 | |
|       for(node_ptr p_left = NodeTraits::get_left(node)
 | |
|          ;p_left
 | |
|          ;p_left = NodeTraits::get_left(node)){
 | |
|          node = p_left;
 | |
|       }
 | |
|       return node;
 | |
|    }
 | |
| 
 | |
|    //! <b>Requires</b>: 'node' is a node of a tree but not the header.
 | |
|    //!
 | |
|    //! <b>Effects</b>: Returns the maximum node of the subtree starting at p.
 | |
|    //!
 | |
|    //! <b>Complexity</b>: Logarithmic to the size of the subtree.
 | |
|    //!
 | |
|    //! <b>Throws</b>: Nothing.
 | |
|    static node_ptr maximum(node_ptr node)
 | |
|    {
 | |
|       for(node_ptr p_right = NodeTraits::get_right(node)
 | |
|          ;p_right
 | |
|          ;p_right = NodeTraits::get_right(node)){
 | |
|          node = p_right;
 | |
|       }
 | |
|       return node;
 | |
|    }
 | |
| 
 | |
|    //! <b>Requires</b>: p is a node of a tree.
 | |
|    //!
 | |
|    //! <b>Effects</b>: Returns true if p is the header of the tree.
 | |
|    //!
 | |
|    //! <b>Complexity</b>: Constant.
 | |
|    //!
 | |
|    //! <b>Throws</b>: Nothing.
 | |
|    static bool is_header(const const_node_ptr & p)
 | |
|    {
 | |
|       node_ptr p_left (NodeTraits::get_left(p));
 | |
|       node_ptr p_right(NodeTraits::get_right(p));
 | |
|       if(!NodeTraits::get_parent(p) || //Header condition when empty tree
 | |
|          (p_left && p_right &&         //Header always has leftmost and rightmost
 | |
|             (p_left == p_right ||      //Header condition when only node
 | |
|                (NodeTraits::get_parent(p_left)  != p ||
 | |
|                 NodeTraits::get_parent(p_right) != p ))
 | |
|                //When tree size > 1 headers can't be leftmost's
 | |
|                //and rightmost's parent
 | |
|           )){
 | |
|          return true;
 | |
|       }
 | |
|       return false;
 | |
|    }
 | |
| 
 | |
|    //! <b>Requires</b>: 'node' is a node of the tree or a header node.
 | |
|    //!
 | |
|    //! <b>Effects</b>: Returns the header of the tree.
 | |
|    //!
 | |
|    //! <b>Complexity</b>: Logarithmic.
 | |
|    //!
 | |
|    //! <b>Throws</b>: Nothing.
 | |
|    static node_ptr get_header(const const_node_ptr & node)
 | |
|    {
 | |
|       node_ptr n(detail::uncast(node));
 | |
|       node_ptr p(NodeTraits::get_parent(node));
 | |
|       //If p is null, then n is the header of an empty tree
 | |
|       if(p){
 | |
|          //Non-empty tree, check if n is neither root nor header
 | |
|          node_ptr pp(NodeTraits::get_parent(p));
 | |
|          //If granparent is not equal to n, then n is neither root nor header,
 | |
|          //the try the fast path
 | |
|          if(n != pp){
 | |
|             do{
 | |
|                n = p;
 | |
|                p = pp;
 | |
|                pp = NodeTraits::get_parent(pp);
 | |
|             }while(n != pp);
 | |
|             n = p;
 | |
|          }
 | |
|          //Check if n is root or header when size() > 0
 | |
|          else if(!bstree_algorithms_base::is_header(n)){
 | |
|             n = p;
 | |
|          }
 | |
|       }
 | |
|       return n;
 | |
|    }
 | |
| };
 | |
| 
 | |
| }  //namespace intrusive
 | |
| }  //namespace boost
 | |
| 
 | |
| #endif //BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP
 | 
