Пример #1
0
/* 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;
    }
}
Пример #2
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)(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;
}
Пример #3
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;
}
Пример #4
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;
		}
	}
}
Пример #5
0
/* 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;
}
Пример #6
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);
   }
}
Пример #7
0
// 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");
   }
}