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 |