tree_algorithms.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,626 行 · 第 1/4 页

HPP
1,626
字号
///////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga  2007.//// 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_TREE_ALGORITHMS_HPP#define BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP#include <boost/intrusive/detail/config_begin.hpp>#include <boost/intrusive/detail/assert.hpp>#include <boost/intrusive/intrusive_fwd.hpp>#include <cstddef>#include <boost/intrusive/detail/utilities.hpp>namespace boost {namespace intrusive {namespace detail {//!   This is an implementation of a binary search tree.//!   A node in the search tree has references to its children and its parent. This //!   is to allow traversal of the whole tree from a given node making the //!   implementation of iterator a pointer to a node.//!   At the top of the tree a node is used specially. This node's parent pointer //!   is pointing to the root of the tree. Its left pointer points to the //!   leftmost node in the tree and the right pointer to the rightmost one.//!   This node is used to represent the end-iterator.//!//!                                            +---------+ //!       header------------------------------>|         | //!                                            |         | //!                   +----------(left)--------|         |--------(right)---------+ //!                   |                        +---------+                        | //!                   |                             |                             | //!                   |                             | (parent)                    |//!                   |                             |                             |//!                   |                             |                             |//!                   |                        +---------+                        |//!    root of tree ..|......................> |         |                        |//!                   |                        |    D    |                        |//!                   |                        |         |                        |//!                   |                +-------+---------+-------+                |//!                   |                |                         |                |//!                   |                |                         |                |//!                   |                |                         |                |//!                   |                |                         |                |//!                   |                |                         |                |//!                   |          +---------+                 +---------+          |//!                   |          |         |                 |         |          |//!                   |          |    B    |                 |    F    |          |//!                   |          |         |                 |         |          |//!                   |       +--+---------+--+           +--+---------+--+       |//!                   |       |               |           |               |       |//!                   |       |               |           |               |       |//!                   |       |               |           |               |       |//!                   |   +---+-----+   +-----+---+   +---+-----+   +-----+---+   |//!                   +-->|         |   |         |   |         |   |         |<--+ //!                       |    A    |   |    C    |   |    E    |   |    G    | //!                       |         |   |         |   |         |   |         | //!                       +---------+   +---------+   +---------+   +---------+ //!//! tree_algorithms is configured with a NodeTraits class, which encapsulates the//! information about the node to be manipulated. NodeTraits must support the//! following interface://!//! <b>Typedefs</b>://!//! <tt>node</tt>: The type of the node that forms the circular list//!//! <tt>node_ptr</tt>: A pointer to a node//!//! <tt>const_node_ptr</tt>: A pointer to a const node//!//! <b>Static functions</b>://!//! <tt>static node_ptr get_parent(const_node_ptr n);</tt>//! //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>//!//! <tt>static node_ptr get_left(const_node_ptr n);</tt>//! //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>//!//! <tt>static node_ptr get_right(const_node_ptr n);</tt>//! //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>template<class NodeTraits>class tree_algorithms{   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;   //! This type is the information that will be filled by insert_unique_check   struct insert_commit_data   {      insert_commit_data()         :  link_left(false)         ,  node(0)      {}      bool     link_left;      node_ptr node;   };   struct nop_erase_fixup   {      void operator()(node_ptr, node_ptr){}   };   /// @cond   private:   template<class Disposer>   struct dispose_subtree_disposer   {      dispose_subtree_disposer(Disposer &disp, node_ptr subtree)         : disposer_(&disp), subtree_(subtree)      {}      void release()      {  disposer_ = 0;  }      ~dispose_subtree_disposer()      {         if(disposer_){            dispose_subtree(subtree_, *disposer_);         }      }      Disposer *disposer_;      node_ptr subtree_;   };   static node_ptr uncast(const_node_ptr ptr)   {      return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));   }   /// @endcond   public:   static node_ptr begin_node(const_node_ptr header)   {  return node_traits::get_left(header);   }   static node_ptr end_node(const_node_ptr header)   {  return uncast(header);   }   //! <b>Requires</b>: node is a node of the tree or an node initialized   //!   by init(...) or init_node.   //!    //! <b>Effects</b>: Returns true if the node is initialized by init() or init_node().   //!    //! <b>Complexity</b>: Constant time.   //!    //! <b>Throws</b>: Nothing.   static bool unique(const_node_ptr node)   { return NodeTraits::get_parent(node) == 0; }   static node_ptr get_header(const_node_ptr node)   {      node_ptr h = uncast(node);      if(NodeTraits::get_parent(node)){         h = NodeTraits::get_parent(node);         while(!is_header(h))            h = NodeTraits::get_parent(h);      }      return h;   }   //! <b>Requires</b>: node1 and node2 can't be header nodes   //!  of two trees.   //!    //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted   //!   in the position node2 before the function. node2 will be inserted in the   //!   position node1 had before the function.   //!    //! <b>Complexity</b>: Logarithmic.    //!    //! <b>Throws</b>: Nothing.   //!    //! <b>Note</b>: This function will break container ordering invariants if   //!   node1 and node2 are not equivalent according to the ordering rules.   //!   //!Experimental function   static void swap_nodes(node_ptr node1, node_ptr node2)   {      if(node1 == node2)         return;         node_ptr header1(get_header(node1)), header2(get_header(node2));      swap_nodes(node1, header1, node2, header2);   }   //! <b>Requires</b>: node1 and node2 can't be header nodes   //!  of two trees with header header1 and header2.   //!    //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted   //!   in the position node2 before the function. node2 will be inserted in the   //!   position node1 had before the function.   //!    //! <b>Complexity</b>: Constant.    //!    //! <b>Throws</b>: Nothing.   //!    //! <b>Note</b>: This function will break container ordering invariants if   //!   node1 and node2 are not equivalent according to the ordering rules.   //!   //!Experimental function   static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2)   {      if(node1 == node2)         return;         //node1 and node2 must not be header nodes       //BOOST_INTRUSIVE_INVARIANT_ASSERT((header1 != node1 && header2 != node2));      if(header1 != header2){         //Update header1 if necessary         if(node1 == NodeTraits::get_left(header1)){            NodeTraits::set_left(header1, node2);         }         if(node1 == NodeTraits::get_right(header1)){            NodeTraits::set_right(header1, node2);         }         if(node1 == NodeTraits::get_parent(header1)){            NodeTraits::set_parent(header1, node2);         }         //Update header2 if necessary         if(node2 == NodeTraits::get_left(header2)){            NodeTraits::set_left(header2, node1);         }         if(node2 == NodeTraits::get_right(header2)){            NodeTraits::set_right(header2, node1);         }         if(node2 == NodeTraits::get_parent(header2)){            NodeTraits::set_parent(header2, node1);         }      }      else{         //If both nodes are from the same tree         //Update header if necessary         if(node1 == NodeTraits::get_left(header1)){            NodeTraits::set_left(header1, node2);         }         else if(node2 == NodeTraits::get_left(header2)){            NodeTraits::set_left(header2, node1);         }         if(node1 == NodeTraits::get_right(header1)){            NodeTraits::set_right(header1, node2);         }         else if(node2 == NodeTraits::get_right(header2)){            NodeTraits::set_right(header2, node1);         }         if(node1 == NodeTraits::get_parent(header1)){            NodeTraits::set_parent(header1, node2);         }         else if(node2 == NodeTraits::get_parent(header2)){            NodeTraits::set_parent(header2, node1);         }         //Adjust data in nodes to be swapped         //so that final link swap works as expected         if(node1 == NodeTraits::get_parent(node2)){            NodeTraits::set_parent(node2, node2);            if(node2 == NodeTraits::get_right(node1)){               NodeTraits::set_right(node1, node1);            }            else{               NodeTraits::set_left(node1, node1);            }         }         else if(node2 == NodeTraits::get_parent(node1)){            NodeTraits::set_parent(node1, node1);            if(node1 == NodeTraits::get_right(node2)){               NodeTraits::set_right(node2, node2);            }            else{               NodeTraits::set_left(node2, node2);            }         }      }      //Now swap all the links      node_ptr temp;      //swap left link      temp = NodeTraits::get_left(node1);      NodeTraits::set_left(node1, NodeTraits::get_left(node2));      NodeTraits::set_left(node2, temp);      //swap right link      temp = NodeTraits::get_right(node1);      NodeTraits::set_right(node1, NodeTraits::get_right(node2));      NodeTraits::set_right(node2, temp);      //swap parent link      temp = NodeTraits::get_parent(node1);      NodeTraits::set_parent(node1, NodeTraits::get_parent(node2));      NodeTraits::set_parent(node2, temp);      //Now adjust adjacent nodes for newly inserted node 1      if((temp = NodeTraits::get_left(node1))){         NodeTraits::set_parent(temp, node1);      }      if((temp = NodeTraits::get_right(node1))){         NodeTraits::set_parent(temp, node1);      }      if((temp = NodeTraits::get_parent(node1)) &&         //The header has been already updated so avoid it         temp != header2){         if(NodeTraits::get_left(temp) == node2){            NodeTraits::set_left(temp, node1);         }         if(NodeTraits::get_right(temp) == node2){            NodeTraits::set_right(temp, node1);         }      }      //Now adjust adjacent nodes for newly inserted node 2      if((temp = NodeTraits::get_left(node2))){         NodeTraits::set_parent(temp, node2);      }      if((temp = NodeTraits::get_right(node2))){         NodeTraits::set_parent(temp, node2);      }      if((temp = NodeTraits::get_parent(node2)) &&         //The header has been already updated so avoid it         temp != header1){         if(NodeTraits::get_left(temp) == node1){            NodeTraits::set_left(temp, node2);         }         if(NodeTraits::get_right(temp) == node1){            NodeTraits::set_right(temp, node2);         }      }   }   //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree   //!   and new_node must not be inserted in a tree.   //!    //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the   //!   tree with new_node. The tree does not need to be rebalanced   //!    //! <b>Complexity</b>: Logarithmic.    //!    //! <b>Throws</b>: Nothing.   //!    //! <b>Note</b>: This function will break container ordering invariants if   //!   new_node is not equivalent to node_to_be_replaced according to the   //!   ordering rules. This function is faster than erasing and inserting   //!   the node, since no rebalancing and comparison is needed.   //!   //!Experimental function   static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node)   {      if(node_to_be_replaced == new_node)         return;      replace_node(node_to_be_replaced, get_header(node_to_be_replaced), new_node);   }   //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree   //!   with header "header" and new_node must not be inserted in a tree.   //!    //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the   //!   tree with new_node. The tree does not need to be rebalanced   //!    //! <b>Complexity</b>: Constant.    //!    //! <b>Throws</b>: Nothing.   //!    //! <b>Note</b>: This function will break container ordering invariants if   //!   new_node is not equivalent to node_to_be_replaced according to the   //!   ordering rules. This function is faster than erasing and inserting   //!   the node, since no rebalancing or comparison is needed.   //!   //!Experimental function   static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node)   {      if(node_to_be_replaced == new_node)         return;         //Update header if necessary      if(node_to_be_replaced == NodeTraits::get_left(header)){         NodeTraits::set_left(header, new_node);      }      if(node_to_be_replaced == NodeTraits::get_right(header)){         NodeTraits::set_right(header, new_node);      }      if(node_to_be_replaced == NodeTraits::get_parent(header)){         NodeTraits::set_parent(header, new_node);      }      //Now set data from the original node      node_ptr temp;      NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?