static void post_insert(struct avl_tree *tree, struct avl_node *node) { struct avl_node *parent = node->parent; if (parent == NULL) return; if (node == parent->left) { parent->balance--; if (parent->balance == 0) return; if (parent->balance == -1) { post_insert(tree, parent); return; } if (node->balance == -1) { avl_rotate_right(tree, parent); return; } avl_rotate_left(tree, node); avl_rotate_right(tree, node->parent->parent); return; } parent->balance++; if (parent->balance == 0) return; if (parent->balance == 1) { post_insert(tree, parent); return; } if (node->balance == 1) { avl_rotate_left(tree, parent); return; } avl_rotate_right(tree, node); avl_rotate_left(tree, node->parent->parent); }
/** * // 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); }
/* ---- * avl_insertinto() - * * The heart of avl_insert(). * ---- */ static int avl_insertinto(AVLtree *tree, AVLnode **node, void *cdata, AVLnode **result) { int cmp; /* * Compare the node at hand with the new elements key. */ cmp = (tree->compfunc) (cdata, (*node)->cdata); if (cmp > 0) { /* * New element is > than node. Insert to the right. */ if ((*node)->rnode == NULL) { /* * Right side of current node is empty. Create a new node there * and return new maximum depth. Note that this can only be 1 * because otherwise this node would have been unbalanced before. */ (*node)->rnode = *result = avl_makenode(); (*node)->rdepth = 1; return 1; } /* * Right hand node exists. Recurse into that and remember the new * right hand side depth. */ (*node)->rdepth = avl_insertinto(tree, &((*node)->rnode), cdata, result) + 1; /* * A right hand side insert can unbalance this node only to the right. */ if (AVL_BALANCE(*node) > 1) { if (AVL_BALANCE((*node)->rnode) > 0) { /* * RR situation, rebalance the tree by left rotating this * node. */ avl_rotate_left(node); } else { /* * RL situation, rebalance the tree by first right rotating * the right hand side, then left rotating this node. */ avl_rotate_right(&((*node)->rnode)); avl_rotate_left(node); } } return AVL_MAXDEPTH(*node); } else if (cmp < 0) { /* * New element is < than node. Insert to the left. */ if ((*node)->lnode == NULL) { /* * Left side of current node is empty. Create a new node there and * return new maximum depth. Note that this can only be 1 because * otherwise this node would have been unbalanced before. */ (*node)->lnode = *result = avl_makenode(); (*node)->ldepth = 1; return AVL_MAXDEPTH(*node); } /* * Left hand node exists. Recurse into that and remember the new left * hand side depth. */ (*node)->ldepth = avl_insertinto(tree, &((*node)->lnode), cdata, result) + 1; /* * A left hand side insert can unbalance this node only to the left. */ if (AVL_BALANCE(*node) < -1) { if (AVL_BALANCE((*node)->lnode) < 0) { /* * LL situation, rebalance the tree by right rotating this * node. */ avl_rotate_right(node); } else { /* * LR situation, rebalance the tree by first left rotating the * left node, then right rotating this node. */ avl_rotate_left(&((*node)->lnode)); avl_rotate_right(node); } } return AVL_MAXDEPTH(*node); } else { /* * The new element is equal to this node. If it is marked for * deletion, free the user element data now. The caller is supposed to * replace it with a new element having the the key. */ if ((*node)->deleted && tree->freefunc != NULL) { (tree->freefunc) ((*node)->cdata); (*node)->cdata = NULL; (*node)->deleted = 0; } *result = *node; return AVL_MAXDEPTH(*node); } }