BSTNode* CC RebalanceRight ( BSTNode *y, BSTNode *x ) { /* detect child balance */ if ( RIGHT_HEAVY ( x ) ) return RotateLeftAtY ( y, x ); /* left heavy */ return RotateRightAtXLeftAtY ( y, x ); }
/** * // node, current node to balance * // root, the root node of the tree * * RETURNS the new child for the parent */ static void avl_balance_node(struct avl_node **parent) { assert(parent != NULL); struct avl_node *node = *parent; // get balance for node short lh = (node->left != NULL) ? node->left->height : 0; short rh = (node->right != NULL) ? node->right->height : 0; short balance = lh - rh; //printf("balance %d\n", balance); if (balance == -1) { // handle right subtree too high assert(node->right != NULL); if((node->right->right != NULL) && (node->right->left != NULL) && LEFT_HEAVY(node->right)) { avl_rotate_right(&(node->right)); } avl_rotate_left(parent); //printf("rotation done\n"); } else if (balance == 1) { // handle left subtree too high // check for left right case assert(node->left != NULL); if((node->left->left != NULL) && (node->left->right != NULL) && RIGHT_HEAVY(node->left)) { avl_rotate_left(&(node->left)); } avl_rotate_right(parent); //printf("rotation done\n"); } else { ; } assert(parent != NULL); assert(*parent != NULL); }
static void CC RebalanceAfterInsert ( BSTNode **root, BSTNode *y, BSTNode *x ) { BSTNode *w, *z; /* detect left insertion */ if ( y -> child [ 0 ] == x ) { /* if y was right-heavy, done */ if ( RIGHT_HEAVY ( y ) ) { CLR_BALANCE ( y, RIGHT ); return; } /* rebalance left insertion */ w = RebalanceLeft ( y, x ); } /* right insertion */ else { /* if y was left-heavy, done */ if ( LEFT_HEAVY ( y ) ) { CLR_BALANCE ( y, LEFT ); return; } /* rebalance right insertion */ w = RebalanceRight ( y, x ); } /* fix parent to child */ assert ( BALANCE ( w ) == 0 ); z = w -> par; if ( z == 0 ) * root = w; else z -> child [ z -> child [ 1 ] == y ] = w; }
/* BSTreeUnlink * removes a node from tree */ static void CC RebalanceAfterUnlink ( BSTNode **root, BSTNode *q, int dir ) { while ( q != 0 ) { BSTNode *w, *x, *y = q; q = PARENT ( q ); if ( ! dir ) { if ( q && q -> child [ 1 ] == y ) dir = 1; /* simulate an increment of balance */ switch ( BALANCE ( y ) ) { case 0: SET_BALANCE ( y, RIGHT ); return; case LEFT: CLR_BALANCE ( y, LEFT ); break; case RIGHT: /* y has just become ++ */ x = y -> child [ 1 ]; if ( LEFT_HEAVY ( x ) ) { w = RotateRightAtXLeftAtY ( y, x ); if ( q == 0 ) * root = w; else q -> child [ dir ] = w; } else { w = y -> child [ 1 ] = x -> child [ 0 ]; x -> child [ 0 ] = y; SET_PARENT ( x, q ); SET_PARENT ( y, x ); if ( w != 0 ) SET_PARENT ( w, y ); if ( q == 0 ) * root = x; else q -> child [ dir ] = x; if ( BALANCE ( x ) == 0 ) { SET_BALANCE ( x, LEFT ); SET_PARBAL ( y, x, RIGHT ); return; } ZERO_BALANCE ( x ); ZERO_BALANCE ( y ); /* y = x; */ } break; } } /* symmetric case */ else { if ( q && q -> child [ 0 ] == y ) dir = 0; switch ( BALANCE ( y ) ) { case 0: SET_BALANCE ( y, LEFT ); return; case LEFT: /* y has just become -- */ x = y -> child [ 0 ]; if ( RIGHT_HEAVY ( x ) ) { w = RotateLeftAtXRightAtY ( y, x ); if ( q == 0 ) * root = w; else q -> child [ dir ] = w; } else { w = x -> child [ 1 ]; y -> child [ 0 ] = w; x -> child [ 1 ] = y; SET_PARENT ( x, q ); SET_PARENT ( y, x ); if ( w != 0 ) SET_PARENT ( w, y ); if ( q == 0 ) * root = x; else q -> child [ dir ] = x; if ( BALANCE ( x ) == 0 ) { SET_BALANCE ( x, RIGHT ); SET_PARBAL ( y, x, LEFT ); return; } ZERO_BALANCE ( x ); ZERO_BALANCE ( y ); /* y = x; */ } break; case RIGHT: CLR_BALANCE ( y, RIGHT ); break; } } } }