/* Remove an element a from the AVL tree t * returns -1 if the depth of the tree has shrunk * Warning: if the element is not present in the tree, * returns 0 as if it had been removed succesfully. */ int avl_remove(avl_tree* t, avl* a) { int b; if (t->root == a) return avl_removeroot(t); b = t->compar(t->root, a); if (b >= 0) { /* remove from the left subtree */ int ch; avl_tree left_subtree; if ((left_subtree.root = t->root->left)) { left_subtree.compar = t->compar; ch = avl_remove(&left_subtree, a); t->root->left = left_subtree.root; if (ch) { switch (t->root->balance++) { case -1: return -1; case 0: return 0; } switch (t->root->right->balance) { case 0: avl_swl(&(t->root)); t->root->balance = -1; t->root->left->balance = 1; return 0; case 1: avl_swl(&(t->root)); t->root->balance = 0; t->root->left->balance = 0; return -1; } avl_swr(&(t->root->right)); avl_swl(&(t->root)); avl_nasty(t->root); return -1; } } } if (b <= 0) { /* remove from the right subtree */ int ch; avl_tree right_subtree; if ((right_subtree.root = t->root->right)) { right_subtree.compar = t->compar; ch = avl_remove(&right_subtree, a); t->root->right = right_subtree.root; if (ch) { switch (t->root->balance--) { case 1: return -1; case 0: return 0; } switch (t->root->left->balance) { case 0: avl_swr(&(t->root)); t->root->balance = 1; t->root->right->balance = -1; return 0; case -1: avl_swr(&(t->root)); t->root->balance = 0; t->root->right->balance = 0; return -1; } avl_swl(&(t->root->left)); avl_swr(&(t->root)); avl_nasty(t->root); return -1; } } } return 0; }
// Remove an already-selected node n from the AVL tree t. // Returns True if the depth of the tree has shrunk. static Bool avl_remove(AvlTree* t, AvlNode* n) { Bool ch; Word cmpres = cmp_key_root(t, n); if (cmpres < 0) { AvlTree left_subtree; // Remove from the left subtree vg_assert(t->root->left); // Only need to set the used fields in the subtree. left_subtree.root = t->root->left; left_subtree.cmp = t->cmp; left_subtree.keyOff = t->keyOff; ch = avl_remove(&left_subtree, n); t->root->left = left_subtree.root; if (ch) { switch (t->root->balance++) { case -1: return True; case 0: return False; } switch (t->root->right->balance) { case 0: avl_swl(&(t->root)); t->root->balance = -1; t->root->left->balance = 1; return False; case 1: avl_swl(&(t->root)); t->root->balance = 0; t->root->left->balance = 0; return True; } avl_swr(&(t->root->right)); avl_swl(&(t->root)); avl_nasty(t->root); return True; } else { return False; } } else if (cmpres > 0) { // Remove from the right subtree AvlTree right_subtree; vg_assert(t->root->right); // Only need to set the used fields in the subtree. right_subtree.root = t->root->right; right_subtree.cmp = t->cmp; right_subtree.keyOff = t->keyOff; ch = avl_remove(&right_subtree, n); t->root->right = right_subtree.root; if (ch) { switch (t->root->balance--) { case 1: return True; case 0: return False; } switch (t->root->left->balance) { case 0: avl_swr(&(t->root)); t->root->balance = 1; t->root->right->balance = -1; return False; case -1: avl_swr(&(t->root)); t->root->balance = 0; t->root->right->balance = 0; return True; } avl_swl(&(t->root->left)); avl_swr(&(t->root)); avl_nasty(t->root); return True; } else { return False; } } else { // Found the node to be removed. vg_assert(t->root == n); return avl_removeroot(t); } }