/* Insert element a into the AVL tree t. Returns True if the depth of the tree has grown. If element with that key is already present, just copy a->val to existing node, first returning old ->val field of existing node in *oldV, so that the caller can finalize it however it wants. */ static Bool avl_insert_wrk ( AvlNode** rootp, /*OUT*/MaybeWord* oldV, AvlNode* a, Word (*kCmp)(Word,Word) ) { Word cmpres; /* initialize */ a->left = 0; a->right = 0; a->balance = 0; oldV->b = False; /* insert into an empty tree? */ if (!(*rootp)) { (*rootp) = a; return True; } cmpres = kCmp( (*rootp)->key, a->key ); if (cmpres > 0) { /* insert into the left subtree */ if ((*rootp)->left) { AvlNode* left_subtree = (*rootp)->left; if (avl_insert_wrk(&left_subtree, oldV, a, kCmp)) { switch ((*rootp)->balance--) { case 1: return False; case 0: return True; case -1: break; default: assert(0); } if ((*rootp)->left->balance < 0) { avl_swr( rootp ); (*rootp)->balance = 0; (*rootp)->right->balance = 0; } else { avl_swl( &((*rootp)->left) ); avl_swr( rootp ); avl_nasty( *rootp ); } } else { (*rootp)->left = left_subtree; } return False; } else { (*rootp)->left = a; if ((*rootp)->balance--) return False; return True; } assert(0);/*NOTREACHED*/ } else if (cmpres < 0) { /* insert into the right subtree */ if ((*rootp)->right) { AvlNode* right_subtree = (*rootp)->right; if (avl_insert_wrk(&right_subtree, oldV, a, kCmp)) { switch((*rootp)->balance++) { case -1: return False; case 0: return True; case 1: break; default: assert(0); } if ((*rootp)->right->balance > 0) { avl_swl( rootp ); (*rootp)->balance = 0; (*rootp)->left->balance = 0; } else { avl_swr( &((*rootp)->right) ); avl_swl( rootp ); avl_nasty( *rootp ); } } else { (*rootp)->right = right_subtree; } return False; } else { (*rootp)->right = a; if ((*rootp)->balance++) return False; return True; } assert(0);/*NOTREACHED*/ } else { /* cmpres == 0, a duplicate - replace the val, but don't incorporate the node in the tree */ oldV->b = True; oldV->w = (*rootp)->val; (*rootp)->val = a->val; 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; }
/* Insert element a into the AVL tree t * returns 1 if the depth of the tree has grown * Warning: do not insert elements already present */ int avl_insert(avl_tree* t, avl* a) { /* initialize */ a->left = 0; a->right = 0; a->balance = 0; /* insert into an empty tree */ if (!t->root) { t->root = a; return 1; } if (t->compar(t->root, a) > 0) { /* insert into the left subtree */ if (t->root->left) { avl_tree left_subtree; left_subtree.root = t->root->left; left_subtree.compar = t->compar; if (avl_insert(&left_subtree, a)) { switch (t->root->balance--) { case 1: return 0; case 0: return 1; } if (t->root->left->balance < 0) { avl_swr(&(t->root)); t->root->balance = 0; t->root->right->balance = 0; } else { avl_swl(&(t->root->left)); avl_swr(&(t->root)); avl_nasty(t->root); } } else t->root->left = left_subtree.root; return 0; } else { t->root->left = a; if (t->root->balance--) return 0; return 1; } } else { /* insert into the right subtree */ if (t->root->right) { avl_tree right_subtree; right_subtree.root = t->root->right; right_subtree.compar = t->compar; if (avl_insert(&right_subtree, a)) { switch (t->root->balance++) { case -1: return 0; case 0: return 1; } if (t->root->right->balance > 0) { avl_swl(&(t->root)); t->root->balance = 0; t->root->left->balance = 0; } else { avl_swr(&(t->root->right)); avl_swl(&(t->root)); avl_nasty(t->root); } } else t->root->right = right_subtree.root; return 0; } else { t->root->right = a; if (t->root->balance++) return 0; return 1; } } }
/* 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); } }
// Insert element e into the non-empty AVL tree t. // Returns True if the depth of the tree has grown. static Bool avl_insert(AvlTree* t, AvlNode* n) { Word cmpres = cmp_key_root(t, n); if (cmpres < 0) { // Insert into the left subtree. if (t->root->left) { // Only need to set the used fields in the subtree. AvlTree left_subtree; left_subtree.root = t->root->left; left_subtree.cmp = t->cmp; left_subtree.keyOff = t->keyOff; if (avl_insert(&left_subtree, n)) { switch (t->root->balance--) { case 1: return False; case 0: return True; } if (t->root->left->balance < 0) { avl_swr(&(t->root)); t->root->balance = 0; t->root->right->balance = 0; } else { avl_swl(&(t->root->left)); avl_swr(&(t->root)); avl_nasty(t->root); } } else { t->root->left=left_subtree.root; } return False; } else { t->root->left = n; if (t->root->balance--) return False; return True; } } else if (cmpres > 0) { // Insert into the right subtree if (t->root->right) { // Only need to set the used fields in the subtree. AvlTree right_subtree; right_subtree.root = t->root->right; right_subtree.cmp = t->cmp; right_subtree.keyOff = t->keyOff; if (avl_insert(&right_subtree, n)) { switch (t->root->balance++) { case -1: return False; case 0: return True; } if (t->root->right->balance > 0) { avl_swl(&(t->root)); t->root->balance = 0; t->root->left->balance = 0; } else { avl_swr(&(t->root->right)); avl_swl(&(t->root)); avl_nasty(t->root); } } else { t->root->right=right_subtree.root; } return False; } else { t->root->right = n; if (t->root->balance++) return False; return True; } } else { vg_assert2(0, "OSet_Insert: duplicate element added"); } }