static void rebalance (c_avl_tree_t *t, c_avl_node_t *n) { int b_top; int b_bottom; while (n != NULL) { b_top = BALANCE (n); assert ((b_top >= -2) && (b_top <= 2)); if (b_top == -2) { assert (n->right != NULL); b_bottom = BALANCE (n->right); assert ((b_bottom >= -1) && (b_bottom <= 1)); if (b_bottom == 1) n = rotate_right_left (t, n); else n = rotate_left (t, n); } else if (b_top == 2) { assert (n->left != NULL); b_bottom = BALANCE (n->left); assert ((b_bottom >= -1) && (b_bottom <= 1)); if (b_bottom == -1) n = rotate_left_right (t, n); else n = rotate_right (t, n); } else { int height = calc_height (n); if (height == n->height) break; n->height = height; } assert (n->height == calc_height (n)); n = n->parent; } /* while (n != NULL) */ } /* void rebalance */
static gpr_avl_node *rebalance(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { switch (node_height(left) - node_height(right)) { case 2: if (node_height(left->left) - node_height(left->right) == -1) { return assert_invariants( rotate_left_right(vtable, key, value, left, right)); } else { return assert_invariants(rotate_right(vtable, key, value, left, right)); } case -2: if (node_height(right->left) - node_height(right->right) == 1) { return assert_invariants( rotate_right_left(vtable, key, value, left, right)); } else { return assert_invariants(rotate_left(vtable, key, value, left, right)); } default: return assert_invariants(new_node(key, value, left, right)); } }
ZIX_PRIVATE ZixTreeNode* zix_tree_rebalance(ZixTree* t, ZixTreeNode* node, int* height_change) { #ifdef ZIX_TREE_HYPER_VERIFY const size_t old_height = height(node); #endif DEBUG_PRINTF("REBALANCE %ld (%d)\n", (intptr_t)node->data, node->balance); *height_change = 0; const bool is_root = !node->parent; assert((is_root && t->root == node) || (!is_root && t->root != node)); ZixTreeNode* replacement = node; if (node->balance == -2) { assert(node->left); if (node->left->balance == 1) { replacement = rotate_left_right(node, height_change); } else { replacement = rotate_right(node, height_change); } } else if (node->balance == 2) { assert(node->right); if (node->right->balance == -1) { replacement = rotate_right_left(node, height_change); } else { replacement = rotate_left(node, height_change); } } if (is_root) { assert(!replacement->parent); t->root = replacement; } DUMP(t); #ifdef ZIX_TREE_HYPER_VERIFY assert(old_height + *height_change == height(replacement)); #endif return replacement; }