tree_algorithms.hpp

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

HPP
1,626
字号
         rightmost_out  = rightmost;      }      return target_sub_root;   }   template<class Disposer>   static void dispose_subtree(node_ptr x, Disposer disposer)   {      node_ptr save;      while (x){         save = NodeTraits::get_left(x);         if (save) {            // Right rotation            NodeTraits::set_left(x, NodeTraits::get_right(save));            NodeTraits::set_right(save, x);         }         else {            save = NodeTraits::get_right(x);            init(x);            disposer(x);         }         x = save;      }   }   //! <b>Requires</b>: p is a node of a tree.   //!    //! <b>Effects</b>: Returns true if p is a left child.   //!    //! <b>Complexity</b>: Constant.   //!    //! <b>Throws</b>: Nothing.   static bool is_left_child(node_ptr p)   {  return NodeTraits::get_left(NodeTraits::get_parent(p)) == p;  }   //! <b>Requires</b>: p is a node of a tree.   //!    //! <b>Effects</b>: Returns true if p is a right child.   //!    //! <b>Complexity</b>: Constant.   //!    //! <b>Throws</b>: Nothing.   static bool is_right_child (node_ptr p)   {  return NodeTraits::get_right(NodeTraits::get_parent(p)) == p;  }   static void replace_own (node_ptr own, node_ptr x, node_ptr header)   {      if(NodeTraits::get_parent(header) == own)         NodeTraits::set_parent(header, x);      else if(is_left_child(own))         NodeTraits::set_left(NodeTraits::get_parent(own), x);      else         NodeTraits::set_right(NodeTraits::get_parent(own), x);   }   static void rotate_left(node_ptr p, node_ptr header)   {      node_ptr x = NodeTraits::get_right(p);      NodeTraits::set_right(p, NodeTraits::get_left(x));      if(NodeTraits::get_left(x) != 0)         NodeTraits::set_parent(NodeTraits::get_left(x), p);      NodeTraits::set_parent(x, NodeTraits::get_parent(p));      replace_own (p, x, header);      NodeTraits::set_left(x, p);      NodeTraits::set_parent(p, x);   }   static void rotate_right(node_ptr p, node_ptr header)   {      node_ptr x(NodeTraits::get_left(p));      node_ptr x_right(NodeTraits::get_right(x));      NodeTraits::set_left(p, x_right);      if(x_right)         NodeTraits::set_parent(x_right, p);      NodeTraits::set_parent(x, NodeTraits::get_parent(p));      replace_own (p, x, header);      NodeTraits::set_right(x, p);      NodeTraits::set_parent(p, x);   }   // rotate node t with left child            | complexity : constant        | exception : nothrow   static node_ptr rotate_left(node_ptr t)   {      node_ptr x = NodeTraits::get_right(t);      NodeTraits::set_right(t, NodeTraits::get_left(x));      if( NodeTraits::get_right(t) != 0 ){         NodeTraits::set_parent(NodeTraits::get_right(t), t );      }      NodeTraits::set_left(x, t);      NodeTraits::set_parent(t, x);      return x;   }   // rotate node t with right child            | complexity : constant        | exception : nothrow   static node_ptr rotate_right(node_ptr t)   {      node_ptr x = NodeTraits::get_left(t);      NodeTraits::set_left(t, NodeTraits::get_right(x));      if( NodeTraits::get_left(t) != 0 ){         NodeTraits::set_parent(NodeTraits::get_left(t), t);      }      NodeTraits::set_right(x, t);      NodeTraits::set_parent(t, x);      return x;   }   static void link(node_ptr header, node_ptr z, node_ptr par, bool left)   {      if(par == header){         NodeTraits::set_parent(header, z);         NodeTraits::set_right(header, z);         NodeTraits::set_left(header, z);      }      else if(left){         NodeTraits::set_left(par, z);         if(par == NodeTraits::get_left(header))             NodeTraits::set_left(header, z);      }      else{         NodeTraits::set_right(par, z);         if(par == NodeTraits::get_right(header))             NodeTraits::set_right(header, z);      }      NodeTraits::set_parent(z, par);      NodeTraits::set_right(z, node_ptr(0));      NodeTraits::set_left(z, node_ptr(0));   }   static void erase(node_ptr header, node_ptr z)   {      data_for_rebalance ignored;      erase(header, z, nop_erase_fixup(), ignored);   }   struct data_for_rebalance   {      node_ptr x;      node_ptr x_parent;      node_ptr y;   };   template<class F>   static void erase(node_ptr header, node_ptr z, F z_and_successor_fixup, data_for_rebalance &info)   {      erase_impl(header, z, info);      if(info.y != z){         z_and_successor_fixup(z, info.y);      }   }   static void unlink(node_ptr node)   {      node_ptr x = NodeTraits::get_parent(node);      if(x){         while(!is_header(x))            x = NodeTraits::get_parent(x);         erase(x, node);      }   }   static void tree_to_vine(node_ptr header)   {  subtree_to_vine(NodeTraits::get_parent(header)); }   static void vine_to_tree(node_ptr header, std::size_t count)   {  vine_to_subtree(NodeTraits::get_parent(header), count);  }   static void rebalance(node_ptr header)   {      //Taken from:      //"Tree rebalancing in optimal time and space"      //Quentin F. Stout and Bette L. Warren      std::size_t len = 0;      subtree_to_vine(NodeTraits::get_parent(header), &len);      vine_to_subtree(NodeTraits::get_parent(header), len);   }   static node_ptr rebalance_subtree(node_ptr old_root)   {      std::size_t len = 0;      node_ptr new_root = subtree_to_vine(old_root, &len);      return vine_to_subtree(new_root, len);   }   static node_ptr subtree_to_vine(node_ptr old_root, std::size_t *plen = 0)   {      std::size_t len;      len = 0;      if(!old_root)   return node_ptr(0);      //To avoid irregularities in the algorithm (old_root can be a      //left or right child or even the root of the tree) just put the       //root as the right child of its parent. Before doing this backup      //information to restore the original relationship after      //the algorithm is applied.      node_ptr super_root = NodeTraits::get_parent(old_root);      BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);      //Get info      node_ptr super_root_right_backup = NodeTraits::get_right(super_root);      bool super_root_is_header   = is_header(super_root);      bool old_root_is_right  = is_right_child(old_root);      node_ptr x(old_root);      node_ptr new_root(x);      node_ptr save;      bool moved_to_right = false;      for( ; x; x = save){         save = NodeTraits::get_left(x);         if(save){            // Right rotation            node_ptr save_right = NodeTraits::get_right(save);            node_ptr x_parent   = NodeTraits::get_parent(x);            NodeTraits::set_parent(save, x_parent);            NodeTraits::set_right (x_parent, save);            NodeTraits::set_parent(x, save);            NodeTraits::set_right (save, x);            NodeTraits::set_left(x, save_right);            if(save_right)               NodeTraits::set_parent(save_right, x);            if(!moved_to_right)               new_root = save;         }         else{            moved_to_right = true;            save = NodeTraits::get_right(x);            ++len;         }      }      if(super_root_is_header){         NodeTraits::set_right(super_root, super_root_right_backup);         NodeTraits::set_parent(super_root, new_root);      }      else if(old_root_is_right){         NodeTraits::set_right(super_root, new_root);      }      else{         NodeTraits::set_right(super_root, super_root_right_backup);         NodeTraits::set_left(super_root, new_root);      }      if(plen) *plen = len;      return new_root;   }   static node_ptr vine_to_subtree(node_ptr old_root, std::size_t count)   {      std::size_t leaf_nodes = count + 1 - ((size_t) 1 << floor_log2 (count + 1));      std::size_t vine_nodes = count - leaf_nodes;      node_ptr new_root = compress_subtree(old_root, leaf_nodes);      while(vine_nodes > 1){         vine_nodes /= 2;         new_root = compress_subtree(new_root, vine_nodes);      }      return new_root;   }   static node_ptr compress_subtree(node_ptr old_root, std::size_t count)   {      if(!old_root)   return old_root;      //To avoid irregularities in the algorithm (old_root can be      //left or right child or even the root of the tree) just put the       //root as the right child of its parent. First obtain      //information to restore the original relationship after      //the algorithm is applied.      node_ptr super_root = NodeTraits::get_parent(old_root);      BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);      //Get info      node_ptr super_root_right_backup = NodeTraits::get_right(super_root);      bool super_root_is_header   = is_header(super_root);      bool old_root_is_right  = is_right_child(old_root);      //Put old_root as right child      NodeTraits::set_right(super_root, old_root);      //Start the compression algorithm                  node_ptr even_parent = super_root;      node_ptr new_root = old_root;      while(count--){         node_ptr even = NodeTraits::get_right(even_parent);         node_ptr odd = NodeTraits::get_right(even);         if(new_root == old_root)            new_root = odd;         node_ptr even_right = NodeTraits::get_left(odd);         NodeTraits::set_right(even, even_right);         if (even_right)            NodeTraits::set_parent(even_right, even);         NodeTraits::set_right(even_parent, odd);         NodeTraits::set_parent(odd, even_parent);         NodeTraits::set_left(odd, even);         NodeTraits::set_parent(even, odd);         even_parent = odd;      }      if(super_root_is_header){         NodeTraits::set_parent(super_root, new_root);         NodeTraits::set_right(super_root, super_root_right_backup);      }      else if(old_root_is_right){         NodeTraits::set_right(super_root, new_root);      }      else{         NodeTraits::set_left(super_root, new_root);         NodeTraits::set_right(super_root, super_root_right_backup);      }      return new_root;   }   //! <b>Requires</b>: "n" must be a node inserted in a tree.   //!   //! <b>Effects</b>: Returns a pointer to the header node of the tree.   //!   //! <b>Complexity</b>: Logarithmic.   //!    //! <b>Throws</b>: Nothing.   static node_ptr get_root(node_ptr node)   {      BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node)));      node_ptr x = NodeTraits::get_parent(node);      if(x){         while(!is_header(x)){            x = NodeTraits::get_parent(x);         }         return x;      }      else{         return node;      }   }   private:   static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info)   {      node_ptr y(z);      node_ptr x;      node_ptr x_parent(0);      node_ptr z_left(NodeTraits::get_left(z));      node_ptr z_right(NodeTraits::get_right(z));      if(!z_left){         x = z_right;    // x might be null.      }      else if(!z_right){ // z has exactly one non-null child. y == z.         x = z_left;       // x is not null.      }      else{         // find z's successor         y = tree_algorithms::minimum (z_right);         x = NodeTraits::get_right(y);     // x might be null.      }      if(y != z){         // relink y in place of z.  y is z's successor         NodeTraits::set_parent(NodeTraits::get_left(z), y);         NodeTraits::set_left(y, NodeTraits::get_left(z));         if(y != NodeTraits::get_right(z)){            x_parent = NodeTraits::get_parent(y);            if(x)               NodeTraits::set_parent(x, x_parent);            NodeTraits::set_left(x_parent, x);   // y must be a child of left_            NodeTraits::set_right(y, NodeTraits::get_right(z));            NodeTraits::set_parent(NodeTraits::get_right(z), y);         }         else            x_parent = y;         tree_algorithms::replace_own (z, y, header);         NodeTraits::set_parent(y, NodeTraits::get_parent(z));      }      else {   // y == z --> z has only one child, or none         x_parent = NodeTraits::get_parent(z);         if(x)            NodeTraits::set_parent(x, x_parent);         tree_algorithms::replace_own (z, x, header);         if(NodeTraits::get_left(header) == z){            NodeTraits::set_left(header, NodeTraits::get_right(z) == 0 ?        // z->get_left() must be null also               NodeTraits::get_parent(z) :  // makes leftmost == header if z == root               tree_algorithms::minimum (x));         }         if(NodeTraits::get_right(header) == z){            NodeTraits::set_right(header, NodeTraits::get_left(z) == 0 ?        // z->get_right() must be null also                              NodeTraits::get_parent(z) :  // makes rightmost == header if z == root                              tree_algorithms::maximum(x));         }      }      info.x = x;      info.x_parent = x_parent;      info.y = y;   }};}  //namespace detail {}  //namespace intrusive }  //namespace boost #include <boost/intrusive/detail/config_end.hpp>#endif //BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP

⌨️ 快捷键说明

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