Example #1
0
void _RBTree_Iterate(
  const RBTree_Control *rbtree,
  RBTree_Visitor        visitor,
  void                 *visitor_arg
)
{
  const RBTree_Node *current = _RBTree_Minimum( rbtree );
  bool               stop = false;

  while ( !stop && current != NULL ) {
    stop = ( *visitor )( current, visitor_arg );

    current = _RBTree_Successor( current );
  }
}
Example #2
0
void _RBTree_Extract(
  RBTree_Control *the_rbtree,
  RBTree_Node    *the_node
)
{
  RBTree_Node     *leaf, *target;
  RBTree_Color     victim_color;
  RBTree_Direction dir;

  /* check if min needs to be updated */
  if ( the_node == the_rbtree->first[ RBT_LEFT ] ) {
    RBTree_Node *next;
    next = _RBTree_Successor( the_node );
    the_rbtree->first[ RBT_LEFT ] = next;
  }

  /* Check if max needs to be updated. min=max for 1 element trees so
   * do not use else if here. */
  if ( the_node == the_rbtree->first[ RBT_RIGHT ] ) {
    RBTree_Node *previous;
    previous = _RBTree_Predecessor( the_node );
    the_rbtree->first[ RBT_RIGHT ] = previous;
  }

  /* if the_node has at most one non-null child then it is safe to proceed
   * check if both children are non-null, if so then we must find a target node
   * either max in node->child[RBT_LEFT] or min in node->child[RBT_RIGHT],
   * and replace the_node with the target node. This maintains the binary
   * search tree property, but may violate the red-black properties.
   */

  if ( the_node->child[ RBT_LEFT ] && the_node->child[ RBT_RIGHT ] ) {
    target = the_node->child[ RBT_LEFT ]; /* find max in node->child[RBT_LEFT] */

    while ( target->child[ RBT_RIGHT ] )
      target = target->child[ RBT_RIGHT ];

    /* if the target node has a child, need to move it up the tree into
     * target's position (target is the right child of target->parent)
     * when target vacates it. if there is no child, then target->parent
     * should become NULL. This may cause the coloring to be violated.
     * For now we store the color of the node being deleted in victim_color.
     */
    leaf = target->child[ RBT_LEFT ];

    if ( leaf ) {
      leaf->parent = target->parent;
    } else {
      /* fix the tree here if the child is a null leaf. */
      _RBTree_Extract_validate( target );
    }

    victim_color = target->color;
    dir = target != target->parent->child[ 0 ];
    target->parent->child[ dir ] = leaf;

    /* now replace the_node with target */
    dir = the_node != the_node->parent->child[ 0 ];
    the_node->parent->child[ dir ] = target;

    /* set target's new children to the original node's children */
    target->child[ RBT_RIGHT ] = the_node->child[ RBT_RIGHT ];

    if ( the_node->child[ RBT_RIGHT ] )
      the_node->child[ RBT_RIGHT ]->parent = target;

    target->child[ RBT_LEFT ] = the_node->child[ RBT_LEFT ];

    if ( the_node->child[ RBT_LEFT ] )
      the_node->child[ RBT_LEFT ]->parent = target;

    /* finally, update the parent node and recolor. target has completely
     * replaced the_node, and target's child has moved up the tree if needed.
     * the_node is no longer part of the tree, although it has valid pointers
     * still.
     */
    target->parent = the_node->parent;
    target->color = the_node->color;
  } else {
    /* the_node has at most 1 non-null child. Move the child in to
     * the_node's location in the tree. This may cause the coloring to be
     * violated. We will fix it later.
     * For now we store the color of the node being deleted in victim_color.
     */
    leaf = the_node->child[ RBT_LEFT ] ?
           the_node->child[ RBT_LEFT ] : the_node->child[ RBT_RIGHT ];

    if ( leaf ) {
      leaf->parent = the_node->parent;
    } else {
      /* fix the tree here if the child is a null leaf. */
      _RBTree_Extract_validate( the_node );
    }

    victim_color = the_node->color;

    /* remove the_node from the tree */
    dir = the_node != the_node->parent->child[ 0 ];
    the_node->parent->child[ dir ] = leaf;
  }

  /* fix coloring. leaf has moved up the tree. The color of the deleted
   * node is in victim_color. There are two cases:
   *   1. Deleted a red node, its child must be black. Nothing must be done.
   *   2. Deleted a black node, its child must be red. Paint child black.
   */
  if ( victim_color == RBT_BLACK ) { /* eliminate case 1 */
    if ( leaf ) {
      leaf->color = RBT_BLACK; /* case 2 */
    }
  }

  /* set root to black, if it exists */
  if ( the_rbtree->root )
    the_rbtree->root->color = RBT_BLACK;
}