Exemple #1
0
static 
AvlNode* avl_find_node ( AvlNode* t, Word k, Word(*kCmp)(UWord,UWord) )
{
   if (kCmp) {
      /* Boxed comparisons */
      Word cmpresS;
      while (True) {
         if (t == NULL) return NULL;
         cmpresS = kCmp(t->key, k);
         if (cmpresS > 0) t = t->child[0]; else
         if (cmpresS < 0) t = t->child[1]; else
         return t;
      }
   } else {
      /* Unboxed comparisons */
      Word  cmpresS; /* signed */
      UWord cmpresU; /* unsigned */
      while (True) {
         if (t == NULL) return NULL; /* unlikely ==> predictable */
         cmpresS = cmp_unsigned_Words( (UWord)t->key, (UWord)k );
         if (cmpresS == 0) return t; /* unlikely ==> predictable */
         cmpresU = (UWord)cmpresS;
         cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1);
         t = t->child[cmpresU];
      }
   }
}
static 
AvlNode* avl_find_node ( AvlNode* t, Word k, Word(*kCmp)(Word,Word) )
{
   Word cmpres;
   while (True) {
      if (t == NULL) return NULL;
      cmpres = kCmp(t->key, k);
      if (cmpres > 0) t = t->left;  else
      if (cmpres < 0) t = t->right; else
      return t;
   }
}
Exemple #3
0
static
Bool avl_find_bounds ( AvlNode* t, 
                       /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP,
                       /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP,
                       UWord minKey, UWord minVal,
                       UWord maxKey, UWord maxVal,
                       UWord key,
                       Word(*kCmp)(UWord,UWord) )
{
   UWord kLowerBound = minKey;
   UWord vLowerBound = minVal;
   UWord kUpperBound = maxKey;
   UWord vUpperBound = maxVal;
   while (t) {
      Word cmpresS = kCmp ? kCmp(t->key, key)
                          : cmp_unsigned_Words(t->key, key);
      if (cmpresS < 0) {
         kLowerBound = t->key;
         vLowerBound = t->val;
         t = t->child[1];
         continue;
      }
      if (cmpresS > 0) {
         kUpperBound = t->key;
         vUpperBound = t->val;
         t = t->child[0];
         continue;
      }
      /* We should never get here.  If we do, it means the given key
         is actually present in the tree, which means the original
         call was invalid -- an error on the caller's part, and we
         cannot give any meaningful values for the bounds.  (Well,
         maybe we could, but we're not gonna.  Ner!) */
      return False;
   }
   if (kMinP) *kMinP = kLowerBound;
   if (vMinP) *vMinP = vLowerBound;
   if (kMaxP) *kMaxP = kUpperBound;
   if (vMaxP) *vMaxP = vUpperBound;
   return True;
}
Exemple #4
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;
}
Exemple #5
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;
    }
}
Exemple #6
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;
}