/* also fixes height */ static void avlRebalance(AvlTree *t) { int d; if (*t != AVL_EMPTY) { for (d = 0; d < 2; d++) { /* maybe child[d] is now too tall */ if (avlGetHeight((*t)->child[d]) > avlGetHeight((*t)->child[!d]) + 1) { /* imbalanced! */ /* how to fix it? */ /* need to look for taller grandchild of child[d] */ if (avlGetHeight((*t)->child[d]->child[d]) > avlGetHeight((*t)->child[d]->child[!d])) { /* same direction grandchild wins, do single rotation */ avlRotate(t, d); } else { /* opposite direction grandchild moves up, do double rotation */ avlRotate(&(*t)->child[d], !d); avlRotate(t, d); } return; /* avlRotate called avlFixHeight */ } } /* update height */ avlFixHeight(*t); } }
/* * After an insertion, possibly rebalance the tree so that the left and right * node heights don't differ by more than 1. * May update *node. */ static void avlAdjustBalance(avl_tree *tree, avl_node **node) { avl_node *current = *node; int b = avlBalance(current) / 2; if (b != 0) { int dir = (1 - b) / 2; if (avlBalance(current->children[dir]) == -b) avlRotate(¤t->children[dir], !dir); current = avlRotate(node, dir); } if (current != tree->end) avlUpdateHeight(current); }