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
							 |