/** @brief Validate and fix-up tree properties for a new insert/colored node * * This routine checks and fixes the Red-Black Tree properties based on * @a the_node being just added to the tree. * * @note It does NOT disable interrupts to ensure the atomicity of the * append operation. */ static void _RBTree_Validate_insert( RBTree_Node *the_node ) { RBTree_Node *parent = _RBTree_Parent( the_node ); RBTree_Color parentcolor; RBTree_Node *grandparent = _RBTree_Parent_and_color( parent, &parentcolor ); /* note: the insert root case is handled already */ /* if the parent is black, nothing needs to be done * otherwise may need to loop a few times */ while ( parentcolor == RBT_RED ) { /* The root is black, so the grandparent must exist */ RBTree_Node *uncle = _RBTree_Sibling( parent, grandparent ); RBTree_Node *grandgrandparent = _RBTree_Parent( grandparent ); /* * If uncle exists and is red, repaint uncle/parent black and grandparent * red. */ if ( uncle != NULL && _RBTree_Color( uncle ) == RBT_RED ) { _RBTree_Set_parent_and_color( parent, grandparent, RBT_BLACK ); _RBTree_Set_parent_and_color( uncle, grandparent, RBT_BLACK ); _RBTree_Set_parent_and_color( grandparent, grandgrandparent, RBT_RED ); the_node = grandparent; parent = grandgrandparent; grandparent = _RBTree_Parent_and_color( parent, &parentcolor ); if ( grandparent == NULL ) break; } else { /* If uncle does not exist or is black */ RBTree_Direction dir = _RBTree_Direction( the_node, parent ); RBTree_Direction parentdir = _RBTree_Direction( parent, grandparent ); /* ensure node is on the same branch direction as parent */ if ( dir != parentdir ) { RBTree_Node *oldparent = parent; parent = the_node; the_node = oldparent; _RBTree_Rotate( oldparent, parentdir ); } _RBTree_Set_color( parent, RBT_BLACK ); _RBTree_Set_parent_and_color( grandparent, grandgrandparent, RBT_RED ); /* now rotate grandparent in the other branch direction (toward uncle) */ _RBTree_Rotate( grandparent, _RBTree_Opposite_direction( parentdir ) ); grandparent = _RBTree_Parent( parent ); break; } } if ( grandparent == NULL ) _RBTree_Set_parent_and_color( the_node, parent, RBT_BLACK ); }
void _RBTree_Iterate_unprotected( const RBTree_Control *rbtree, RBTree_Direction dir, RBTree_Visitor visitor, void *visitor_arg ) { RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); const RBTree_Node *current = _RBTree_First( rbtree, opp_dir ); bool stop = false; while ( !stop && current != NULL ) { stop = (*visitor)( current, dir, visitor_arg ); current = _RBTree_Next_unprotected( current, dir ); } }
/** @brief Validate and fix-up tree properties after deleting a node * * This routine is called on a black node, @a the_node, after its deletion. * This function maintains the properties of the red-black tree. * * @note It does NOT disable interrupts to ensure the atomicity * of the extract operation. */ static void _RBTree_Extract_validate( RBTree_Node *the_node ) { RBTree_Node *parent; parent = the_node->parent; if ( !parent->parent ) return; /* continue to correct tree as long as the_node is black and not the root */ while ( !_RBTree_Is_red( the_node ) && parent->parent ) { RBTree_Node *sibling = _RBTree_Sibling( the_node, parent ); /* if sibling is red, switch parent (black) and sibling colors, * then rotate parent left, making the sibling be the_node's grandparent. * Now the_node has a black sibling and red parent. After rotation, * update sibling pointer. */ if ( _RBTree_Is_red( sibling ) ) { RBTree_Direction dir = _RBTree_Direction( the_node, parent ); RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); parent->color = RBT_RED; sibling->color = RBT_BLACK; _RBTree_Rotate( parent, dir ); sibling = parent->child[ opp_dir ]; } /* sibling is black, see if both of its children are also black. */ if ( !_RBTree_Is_red( sibling->child[ RBT_RIGHT ] ) && !_RBTree_Is_red( sibling->child[ RBT_LEFT ] ) ) { sibling->color = RBT_RED; if ( _RBTree_Is_red( parent ) ) { parent->color = RBT_BLACK; break; } the_node = parent; /* done if parent is red */ parent = the_node->parent; } else { /* at least one of sibling's children is red. we now proceed in two * cases, either the_node is to the left or the right of the parent. * In both cases, first check if one of sibling's children is black, * and if so rotate in the proper direction and update sibling pointer. * Then switch the sibling and parent colors, and rotate through parent. */ RBTree_Direction dir = _RBTree_Direction( the_node, parent ); RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); if ( !_RBTree_Is_red( sibling->child[ opp_dir ] ) ) { sibling->color = RBT_RED; sibling->child[ dir ]->color = RBT_BLACK; _RBTree_Rotate( sibling, opp_dir ); sibling = parent->child[ opp_dir ]; } sibling->color = parent->color; parent->color = RBT_BLACK; sibling->child[ opp_dir ]->color = RBT_BLACK; _RBTree_Rotate( parent, dir ); break; /* done */ } } /* while */ if ( !the_node->parent->parent ) the_node->color = RBT_BLACK; }
/** @brief Validate and fix-up tree properties after deleting a node * * This routine is called on a black node, @a the_node, after its deletion. * This function maintains the properties of the red-black tree. */ static void rtems_rbtree_extract_validate( RBTree_Node *the_node ) { RBTree_Color color; RBTree_Node *parent = _RBTree_Parent_and_color( the_node, &color ); RBTree_Color parentcolor; RBTree_Node *grandparent = _RBTree_Parent_and_color( parent, &parentcolor ); if ( grandparent == NULL ) return; /* continue to correct tree as long as the_node is black and not the root */ while ( grandparent != NULL && color == RBT_BLACK ) { RBTree_Node *sibling = _RBTree_Sibling( the_node, parent ); /* if sibling is red, switch parent (black) and sibling colors, * then rotate parent left, making the sibling be the_node's grandparent. * Now the_node has a black sibling and red parent. After rotation, * update sibling pointer. */ if ( _RBTree_Color( sibling ) == RBT_RED ) { RBTree_Direction dir = _RBTree_Direction( the_node, parent ); RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); parentcolor = RBT_RED; _RBTree_Set_parent_and_color( parent, grandparent, parentcolor ); _RBTree_Set_parent_and_color( sibling, parent, RBT_BLACK ); _RBTree_Rotate( parent, dir ); grandparent = sibling; sibling = parent->child[ opp_dir ]; } /* sibling is black, see if both of its children are also black. */ if ( _RBTree_Is_null_or_black( sibling->child[ RBT_RIGHT ] ) && _RBTree_Is_null_or_black( sibling->child[ RBT_LEFT ] ) ) { _RBTree_Set_parent_and_color( sibling, parent, RBT_RED ); if ( parentcolor == RBT_RED ) { _RBTree_Set_parent_and_color( parent, grandparent, RBT_BLACK ); break; } the_node = parent; /* done if parent is red */ parent = grandparent; grandparent = _RBTree_Parent_and_color( parent, &parentcolor ); } else { /* at least one of sibling's children is red. we now proceed in two * cases, either the_node is to the left or the right of the parent. * In both cases, first check if one of sibling's children is black, * and if so rotate in the proper direction and update sibling pointer. * Then switch the sibling and parent colors, and rotate through parent. */ RBTree_Direction dir = _RBTree_Direction( the_node, parent ); RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); if ( _RBTree_Is_null_or_black( sibling->child[ opp_dir ] ) ) { _RBTree_Set_parent_and_color( sibling, parent, RBT_RED ); _RBTree_Set_parent_and_color( sibling->child[ dir ], sibling, RBT_BLACK ); _RBTree_Rotate( sibling, opp_dir ); sibling = parent->child[ opp_dir ]; } _RBTree_Set_parent_and_color( sibling, parent, parentcolor ); _RBTree_Set_parent_and_color( parent, grandparent, RBT_BLACK ); _RBTree_Set_parent_and_color( sibling->child[ opp_dir ], sibling, RBT_BLACK ); _RBTree_Rotate( parent, dir ); grandparent = sibling; break; /* done */ } } /* while */ if ( grandparent == NULL ) _RBTree_Set_parent_and_color( the_node, parent, RBT_BLACK ); }