/* Remove the root of the AVL tree *rootp. * Warning: dumps core if *rootp is empty */ static Bool avl_removeroot_wrk ( AvlNode** rootp, Word(*kCmp)(Word,Word) ) { Bool ch; AvlNode* a; if (!(*rootp)->left) { if (!(*rootp)->right) { (*rootp) = 0; return True; } (*rootp) = (*rootp)->right; return True; } if (!(*rootp)->right) { (*rootp) = (*rootp)->left; return True; } if ((*rootp)->balance < 0) { /* remove from the left subtree */ a = (*rootp)->left; while (a->right) a = a->right; } else { /* remove from the right subtree */ a = (*rootp)->right; while (a->left) a = a->left; } ch = avl_remove_wrk(rootp, a, kCmp); a->left = (*rootp)->left; a->right = (*rootp)->right; a->balance = (*rootp)->balance; (*rootp) = a; if(a->balance == 0) return ch; return False; }
// Delete key from fm, returning associated val if found Bool delFromFM ( WordFM* fm, /*OUT*/Word* oldV, Word key ) { AvlNode* node = avl_find_node( fm->root, key, fm->kCmp ); if (node) { avl_remove_wrk( &fm->root, node, fm->kCmp ); if (oldV) *oldV = node->val; fm->dealloc(node); return True; } else { return False; } }
/* Remove an element a from the AVL tree t. a must be part of the tree. Returns True if the depth of the tree has shrunk. */ static Bool avl_remove_wrk ( AvlNode** rootp, AvlNode* a, Word(*kCmp)(Word,Word) ) { Bool ch; Word cmpres = kCmp( (*rootp)->key, a->key ); if (cmpres > 0) { /* remove from the left subtree */ AvlNode* left_subtree = (*rootp)->left; assert(left_subtree); ch = avl_remove_wrk(&left_subtree, a, kCmp); (*rootp)->left=left_subtree; if (ch) { switch ((*rootp)->balance++) { case -1: return True; case 0: return False; case 1: break; default: assert(0); } switch ((*rootp)->right->balance) { case 0: avl_swl( rootp ); (*rootp)->balance = -1; (*rootp)->left->balance = 1; return False; case 1: avl_swl( rootp ); (*rootp)->balance = 0; (*rootp)->left->balance = 0; return -1; case -1: break; default: assert(0); } avl_swr( &((*rootp)->right) ); avl_swl( rootp ); avl_nasty( *rootp ); return True; } } else if (cmpres < 0) { /* remove from the right subtree */ AvlNode* right_subtree = (*rootp)->right; assert(right_subtree); ch = avl_remove_wrk(&right_subtree, a, kCmp); (*rootp)->right = right_subtree; if (ch) { switch ((*rootp)->balance--) { case 1: return True; case 0: return False; case -1: break; default: assert(0); } switch ((*rootp)->left->balance) { case 0: avl_swr( rootp ); (*rootp)->balance = 1; (*rootp)->right->balance = -1; return False; case -1: avl_swr( rootp ); (*rootp)->balance = 0; (*rootp)->right->balance = 0; return True; case 1: break; default: assert(0); } avl_swl( &((*rootp)->left) ); avl_swr( rootp ); avl_nasty( *rootp ); return True; } } else { assert(cmpres == 0); assert((*rootp)==a); return avl_removeroot_wrk(rootp, kCmp); } return 0; }
/* Remove an element a from the AVL tree t. a must be part of the tree. Returns True if the depth of the tree has shrunk. */ static Bool avl_remove_wrk ( AvlNode** rootp, AvlNode* a, Word(*kCmp)(UWord,UWord) ) { Bool ch; Word cmpres; cmpres = kCmp ? /*boxed*/ kCmp( (*rootp)->key, a->key ) : /*unboxed*/ cmp_unsigned_Words( (UWord)(*rootp)->key, (UWord)a->key ); if (cmpres > 0){ /* remove from the left subtree */ AvlNode* left_subtree = (*rootp)->child[0]; tl_assert(left_subtree); ch = avl_remove_wrk(&left_subtree, a, kCmp); (*rootp)->child[0]=left_subtree; if (ch) { switch ((*rootp)->balance++) { case -1: return True; case 0: return False; case 1: break; default: tl_assert(0); } switch ((*rootp)->child[1]->balance) { case 0: avl_swl( rootp ); (*rootp)->balance = -1; (*rootp)->child[0]->balance = 1; return False; case 1: avl_swl( rootp ); (*rootp)->balance = 0; (*rootp)->child[0]->balance = 0; return True; case -1: break; default: tl_assert(0); } avl_swr( &((*rootp)->child[1]) ); avl_swl( rootp ); avl_nasty( *rootp ); return True; } } else if (cmpres < 0) { /* remove from the right subtree */ AvlNode* right_subtree = (*rootp)->child[1]; tl_assert(right_subtree); ch = avl_remove_wrk(&right_subtree, a, kCmp); (*rootp)->child[1] = right_subtree; if (ch) { switch ((*rootp)->balance--) { case 1: return True; case 0: return False; case -1: break; default: tl_assert(0); } switch ((*rootp)->child[0]->balance) { case 0: avl_swr( rootp ); (*rootp)->balance = 1; (*rootp)->child[1]->balance = -1; return False; case -1: avl_swr( rootp ); (*rootp)->balance = 0; (*rootp)->child[1]->balance = 0; return True; case 1: break; default: tl_assert(0); } avl_swl( &((*rootp)->child[0]) ); avl_swr( rootp ); avl_nasty( *rootp ); return True; } } else { tl_assert(cmpres == 0); tl_assert((*rootp)==a); return avl_removeroot_wrk(rootp, kCmp); } return 0; }