Alien-boost-mini

 view release on metacpan or  search on metacpan

include/boost/intrusive/bstree_algorithms.hpp  view on Meta::CPAN

            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
   BOOST_INTRUSIVE_FORCEINLINE static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
   {
      if(node_to_be_replaced == new_node)
         return;
      replace_node(node_to_be_replaced, base_type::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(const node_ptr & node_to_be_replaced, const node_ptr & header, const 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));
      NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced));
      NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced));

      //Now adjust adjacent nodes for newly inserted node
      if((temp = NodeTraits::get_left(new_node))){
         NodeTraits::set_parent(temp, new_node);
      }
      if((temp = NodeTraits::get_right(new_node))){
         NodeTraits::set_parent(temp, new_node);
      }
      if((temp = NodeTraits::get_parent(new_node)) &&
         //The header has been already updated so avoid it
         temp != header){
         if(NodeTraits::get_left(temp) == node_to_be_replaced){
            NodeTraits::set_left(temp, new_node);
         }
         if(NodeTraits::get_right(temp) == node_to_be_replaced){
            NodeTraits::set_right(temp, new_node);
         }
      }
   }

   #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
   //! <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);

   //! <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);

   //! <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);

   //! <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);
   #endif

   //! <b>Requires</b>: 'node' must not be part of any tree.
   //!
   //! <b>Effects</b>: After the function unique(node) == true.
   //!
   //! <b>Complexity</b>: Constant.
   //!
   //! <b>Throws</b>: Nothing.
   //!
   //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
   BOOST_INTRUSIVE_FORCEINLINE static void init(const node_ptr & node)
   {
      NodeTraits::set_parent(node, node_ptr());

include/boost/intrusive/bstree_algorithms.hpp  view on Meta::CPAN


   //Fix header and own's parent data when replacing x with own, providing own's old data with parent
   static void set_child(const node_ptr & header, const node_ptr & new_child, const node_ptr & new_parent, const bool link_left)
   {
      if(new_parent == header)
         NodeTraits::set_parent(header, new_child);
      else if(link_left)
         NodeTraits::set_left(new_parent, new_child);
      else
         NodeTraits::set_right(new_parent, new_child);
   }

   // rotate p to left (no header and p's parent fixup)
   static void rotate_left_no_parent_fix(const node_ptr & p, const node_ptr &p_right)
   {
      node_ptr p_right_left(NodeTraits::get_left(p_right));
      NodeTraits::set_right(p, p_right_left);
      if(p_right_left){
         NodeTraits::set_parent(p_right_left, p);
      }
      NodeTraits::set_left(p_right, p);
      NodeTraits::set_parent(p, p_right);
   }

   // rotate p to left (with header and p's parent fixup)
   static void rotate_left(const node_ptr & p, const node_ptr & p_right, const node_ptr & p_parent, const node_ptr & header)
   {
      const bool p_was_left(NodeTraits::get_left(p_parent) == p);
      rotate_left_no_parent_fix(p, p_right);
      NodeTraits::set_parent(p_right, p_parent);
      set_child(header, p_right, p_parent, p_was_left);
   }

   // rotate p to right (no header and p's parent fixup)
   static void rotate_right_no_parent_fix(const node_ptr & p, const node_ptr &p_left)
   {
      node_ptr p_left_right(NodeTraits::get_right(p_left));
      NodeTraits::set_left(p, p_left_right);
      if(p_left_right){
         NodeTraits::set_parent(p_left_right, p);
      }
      NodeTraits::set_right(p_left, p);
      NodeTraits::set_parent(p, p_left);
   }

   // rotate p to right (with header and p's parent fixup)
   static void rotate_right(const node_ptr & p, const node_ptr & p_left, const node_ptr & p_parent, const node_ptr & header)
   {
      const bool p_was_left(NodeTraits::get_left(p_parent) == p);
      rotate_right_no_parent_fix(p, p_left);
      NodeTraits::set_parent(p_left, p_parent);
      set_child(header, p_left, p_parent, p_was_left);
   }

   private:

   static void subtree_to_vine(node_ptr vine_tail, std::size_t &size)
   {
      //Inspired by LibAVL:
      //It uses a clever optimization for trees with parent pointers.
      //No parent pointer is updated when transforming a tree to a vine as
      //most of them will be overriten during compression rotations.
      //A final pass must be made after the rebalancing to updated those
      //pointers not updated by tree_to_vine + compression calls
      std::size_t len = 0;
      node_ptr remainder = NodeTraits::get_right(vine_tail);
      while(remainder){
         node_ptr tempptr = NodeTraits::get_left(remainder);
         if(!tempptr){   //move vine-tail down one
            vine_tail = remainder;
            remainder = NodeTraits::get_right(remainder);
            ++len;
         }
         else{ //rotate
            NodeTraits::set_left(remainder, NodeTraits::get_right(tempptr));
            NodeTraits::set_right(tempptr, remainder);
            remainder = tempptr;
            NodeTraits::set_right(vine_tail, tempptr);
         }
      }
      size = len;
   }

   static void compress_subtree(node_ptr scanner, std::size_t count)
   {
      while(count--){   //compress "count" spine nodes in the tree with pseudo-root scanner
         node_ptr child = NodeTraits::get_right(scanner);
         node_ptr child_right = NodeTraits::get_right(child);
         NodeTraits::set_right(scanner, child_right);
         //Avoid setting the parent of child_right
         scanner = child_right;
         node_ptr scanner_left = NodeTraits::get_left(scanner);
         NodeTraits::set_right(child, scanner_left);
         if(scanner_left)
            NodeTraits::set_parent(scanner_left, child);
         NodeTraits::set_left(scanner, child);
         NodeTraits::set_parent(child, scanner);
      }
   }

   static void vine_to_subtree(const node_ptr & super_root, std::size_t count)
   {
      const std::size_t one_szt = 1u;
      std::size_t leaf_nodes = count + one_szt - std::size_t(one_szt << detail::floor_log2(count + one_szt));
      compress_subtree(super_root, leaf_nodes);  //create deepest leaves
      std::size_t vine_nodes = count - leaf_nodes;
      while(vine_nodes > 1){
         vine_nodes /= 2;
         compress_subtree(super_root, vine_nodes);
      }

      //Update parents of nodes still in the in the original vine line
      //as those have not been updated by subtree_to_vine or compress_subtree
      for ( node_ptr q = super_root, p = NodeTraits::get_right(super_root)
          ; p
          ; q = p, p = NodeTraits::get_right(p)){
         NodeTraits::set_parent(p, q);
      }
   }

   //! <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(const node_ptr & node)
   {
      BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node)));
      node_ptr x = NodeTraits::get_parent(node);
      if(x){
         while(!base_type::is_header(x)){
            x = NodeTraits::get_parent(x);
         }
         return x;
      }
      else{
         return node;
      }
   }

   template <class Cloner, class Disposer>
   static node_ptr clone_subtree
      (const const_node_ptr &source_parent, const node_ptr &target_parent
      , Cloner cloner, Disposer disposer
      , node_ptr &leftmost_out, node_ptr &rightmost_out
      )
   {
      node_ptr target_sub_root = target_parent;
      node_ptr source_root = NodeTraits::get_parent(source_parent);
      if(!source_root){
         leftmost_out = rightmost_out = source_root;
      }
      else{
         //We'll calculate leftmost and rightmost nodes while iterating
         node_ptr current = source_root;
         node_ptr insertion_point = target_sub_root = cloner(current);

         //We'll calculate leftmost and rightmost nodes while iterating
         node_ptr leftmost  = target_sub_root;
         node_ptr rightmost = target_sub_root;

         //First set the subroot
         NodeTraits::set_left(target_sub_root, node_ptr());
         NodeTraits::set_right(target_sub_root, node_ptr());
         NodeTraits::set_parent(target_sub_root, target_parent);

         dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
         while(true) {
            //First clone left nodes
            if( NodeTraits::get_left(current) &&
               !NodeTraits::get_left(insertion_point)) {



( run in 0.352 second using v1.01-cache-2.11-cpan-172d661cebc )