Beispiel #1
0
avl_node *
avl_new_avl_node (void *            key,
                  avl_node *        parent)
{
  avl_node * node = (avl_node *) malloc (sizeof (avl_node));

  if (!node) {
    return NULL;
  } else {
    node->parent = parent;
    node->key = key;
    node->left = NULL;
    node->right = NULL;
    node->rank_and_balance = 0;
    AVL_SET_BALANCE (node, 0);
    AVL_SET_RANK (node, 1);
    return node;
  }
}
Beispiel #2
0
avl_node *
avl_node_new (void *        key,
          avl_node *    parent)
{
  avl_node * node = (avl_node *) malloc (sizeof (avl_node));
  if (!node)
    abort();

  node->parent = parent;
  node->key = key;
  node->left = NULL;
  node->right = NULL;
  node->rank_and_balance = 0;
  AVL_SET_BALANCE (node, 0);
  AVL_SET_RANK (node, 1);
#ifdef HAVE_AVL_NODE_LOCK
  thread_rwlock_create(&node->rwlock);
#endif
  return node;
}
Beispiel #3
0
int avl_delete(avl_tree *tree, void *key, avl_free_key_fun_type free_key_fun)
{
  avl_node *x, *y, *p, *q, *r, *top, *x_child;
  int shortened_side, shorter;
  
  x = tree->root->right;
  if (!x) {
    return -1;
  }
  while (1) {
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
    if (compare_result < 0) {
      /* move left
       * We will be deleting from the left, adjust this node's
       * rank accordingly
       */
      AVL_SET_RANK (x, (AVL_GET_RANK(x) - 1));
      if (x->left) {
    x = x->left;
      } else {
    /* Oops! now we have to undo the rank changes
     * all the way up the tree
     */
    AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1));
    while (x != tree->root->right) {
      if (x->parent->left == x) {
        AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1));
      }
      x = x->parent;
    }
    return -1;        /* key not in tree */
      }
    } else if (compare_result > 0) {
      /* move right */
      if (x->right) {
    x = x->right;
      } else {
    AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1));
    while (x != tree->root->right) {
      if (x->parent->left == x) {
        AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1));
      }
      x = x->parent;
    }
    return -1;        /* key not in tree */
      }
    } else {
      break;
    }
  }

  if (x->left && x->right) {
    void * temp_key;

    /* The complicated case.
     * reduce this to the simple case where we are deleting
     * a node with at most one child.
     */
    
    /* find the immediate predecessor <y> */
    y = x->left;
    while (y->right) {
      y = y->right;
    }
    /* swap <x> with <y> */
    temp_key = x->key;
    x->key = y->key;
    y->key = temp_key;
    /* we know <x>'s left subtree lost a node because that's
     * where we took it from
     */
    AVL_SET_RANK (x, (AVL_GET_RANK (x) - 1));
    x = y;
  }
  /* now <x> has at most one child
   * scoot this child into the place of <x>
   */
  if (x->left) {
    x_child = x->left;
    x_child->parent = x->parent;
  } else if (x->right) {
    x_child = x->right;
    x_child->parent = x->parent;
  } else {
    x_child = NULL;
  }

  /* now tell <x>'s parent that a grandchild became a child */
  if (x == x->parent->left) {
    x->parent->left = x_child;
    shortened_side = -1;
  } else {
    x->parent->right = x_child;
    shortened_side = +1;
  }

  /*
   * the height of the subtree <x>
   * has now been shortened.  climb back up
   * the tree, rotating when necessary to adjust
   * for the change.
   */
  shorter = 1;
  p = x->parent;
  
  /* return the key and node to storage */
  if (free_key_fun)
      free_key_fun (x->key);
#ifdef HAVE_AVL_NODE_LOCK
  thread_rwlock_destroy (&x->rwlock);
#endif
  free (x);

  while (shorter && p->parent) {
    
    /* case 1: height unchanged */
    if (AVL_GET_BALANCE(p) == 0) {
      if (shortened_side == -1) {
    /* we removed a left child, the tree is now heavier
     * on the right
     */
    AVL_SET_BALANCE (p, +1);
      } else {
    /* we removed a right child, the tree is now heavier
     * on the left
     */
    AVL_SET_BALANCE (p, -1);
      }
      shorter = 0;
      
    } else if (AVL_GET_BALANCE (p) == shortened_side) {
      /* case 2: taller subtree shortened, height reduced */
      AVL_SET_BALANCE (p, 0);
    } else {
      /* case 3: shorter subtree shortened */
      top = p->parent;
      /* set <q> to the taller of the two subtrees of <p> */
      if (shortened_side == 1) {
    q = p->left;
      } else {
    q = p->right;
      }
      if (AVL_GET_BALANCE (q) == 0) {
    /* case 3a: height unchanged */
    if (shortened_side == -1) {
      /* single rotate left */
      q->parent = p->parent;
      p->right = q->left;
      if (q->left) {
        q->left->parent = p;
      }
      q->left = p;
      p->parent = q;
      AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p)));
    } else {
      /* single rotate right */
      q->parent = p->parent;
      p->left = q->right;
      if (q->right) {
        q->right->parent = p;
      }
      q->right = p;
      p->parent = q;
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q)));
    }
    shorter = 0;
    AVL_SET_BALANCE (q, shortened_side);
    AVL_SET_BALANCE (p, (- shortened_side));
      } else if (AVL_GET_BALANCE (q) == AVL_GET_BALANCE (p)) {
    /* case 3b: height reduced */
    if (shortened_side == -1) {
      /* single rotate left */
      q->parent = p->parent;
      p->right = q->left;
      if (q->left) {
        q->left->parent = p;
      }
      q->left = p;
      p->parent = q;
      AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p)));
    } else {
      /* single rotate right */
      q->parent = p->parent;
      p->left = q->right;
      if (q->right) {
        q->right->parent = p;
      }
      q->right = p;
      p->parent = q;
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q)));
    }
    shorter = 1;
    AVL_SET_BALANCE (q, 0);
    AVL_SET_BALANCE (p, 0);
      } else {
    /* case 3c: height reduced, balance factors opposite */
    if (shortened_side == 1) {
      /* double rotate right */
      /* first, a left rotation around q */
      r = q->right;
      r->parent = p->parent;
      q->right = r->left;
      if (r->left) {
        r->left->parent = q;
      }
      r->left = q;
      q->parent = r;
      /* now, a right rotation around p */
      p->left = r->right;
      if (r->right) {
        r->right->parent = p;
      }
      r->right = p;
      p->parent = r;
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (q)));
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (r)));
    } else {
      /* double rotate left */
      /* first, a right rotation around q */
      r = q->left;
      r->parent = p->parent;
      q->left = r->right;
      if (r->right) {
        r->right->parent = q;
      }
      r->right = q;
      q->parent = r;
      /* now a left rotation around p */
      p->right = r->left;
      if (r->left) {
        r->left->parent = p;
      }
      r->left = p;
      p->parent = r;
      AVL_SET_RANK (q, (AVL_GET_RANK (q) - AVL_GET_RANK (r)));
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (p)));        
    }
    if (AVL_GET_BALANCE (r) == shortened_side) {
      AVL_SET_BALANCE (q, (- shortened_side));
      AVL_SET_BALANCE (p, 0);
    } else if (AVL_GET_BALANCE (r) == (- shortened_side)) {
      AVL_SET_BALANCE (q, 0);
      AVL_SET_BALANCE (p, shortened_side);
    } else {
      AVL_SET_BALANCE (q, 0);
      AVL_SET_BALANCE (p, 0);
    }
    AVL_SET_BALANCE (r, 0);
    q = r;
      }
      /* a rotation has caused <q> (or <r> in case 3c) to become
       * the root.  let <p>'s former parent know this.
       */
      if (top->left == p) {
    top->left = q;
      } else {
    top->right = q;
      }
      /* end case 3 */
      p = q;
    }
    x = p;
    p = x->parent;
    /* shortened_side tells us which side we came up from */
    if (x == p->left) {
      shortened_side = -1;
    } else {
      shortened_side = +1;
    }
  } /* end while(shorter) */
  /* when we're all done, we're one shorter */
  tree->length = tree->length - 1;
  return (0);
}
Beispiel #4
0
int
avl_insert (avl_tree * ob,
           void * key)
{
  if (!(ob->root->right)) {
    avl_node * node = avl_node_new (key, ob->root);
    if (!node) {
      return -1;
    } else {
      ob->root->right = node;
      ob->length = ob->length + 1;
      return 0;
    }
  } else { /* not self.right == None */
    avl_node *t, *p, *s, *q, *r;
    int a;

    t = ob->root;
    s = p = t->right;

    while (1) {
      if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) {
    /* move left */
    AVL_SET_RANK (p, (AVL_GET_RANK (p) + 1));
    q = p->left;
    if (!q) {
      /* insert */
      avl_node * q_node = avl_node_new (key, p);
      if (!q_node) {
        return (-1);
      } else {
        q = q_node;
        p->left = q;
        break;
      }
    } else if (AVL_GET_BALANCE(q)) {
      t = p;
      s = q;
    }
    p = q;
      } else {
    /* move right */
    q = p->right;
    if (!q) {
      /* insert */
      avl_node * q_node = avl_node_new (key, p);
      if (!q_node) {
        return -1;
      } else {
        q = q_node;
        p->right = q;
        break;
      }
    } else if (AVL_GET_BALANCE(q)) {
      t = p;
      s = q;
    }
    p = q;
      }
    }
    
    ob->length = ob->length + 1;
    
    /* adjust balance factors */
    if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) {
      r = p = s->left;
    } else {
      r = p = s->right;
    }
    while (p != q) {
      if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) {
    AVL_SET_BALANCE (p, -1);
    p = p->left;
      } else {
    AVL_SET_BALANCE (p, +1);
    p = p->right;
      }
    }
    
    /* balancing act */
    
    if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) {
      a = -1;
    } else {
      a = +1;
    }
    
    if (AVL_GET_BALANCE (s) == 0) {
      AVL_SET_BALANCE (s, a);
      ob->height = ob->height + 1;
      return 0;
    } else if (AVL_GET_BALANCE (s) == -a) {
      AVL_SET_BALANCE (s, 0);
      return 0;
    } else if (AVL_GET_BALANCE(s) == a) {
      if (AVL_GET_BALANCE (r) == a) {
    /* single rotation */
    p = r;
    if (a == -1) {
      s->left = r->right;
      if (r->right) {
        r->right->parent = s;
      }
      r->right = s;
      s->parent = r;
      AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (r)));
    } else {
      s->right = r->left;
      if (r->left) {
        r->left->parent = s;
      }
      r->left = s;
      s->parent = r;
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (s)));
    }
    AVL_SET_BALANCE (s, 0);
    AVL_SET_BALANCE (r, 0);
      } else if (AVL_GET_BALANCE (r) == -a) {
    /* double rotation */
    if (a == -1) {
      p = r->right;
      r->right = p->left;
      if (p->left) {
        p->left->parent = r;
      }
      p->left = r;
      r->parent = p;
      s->left = p->right;
      if (p->right) {
        p->right->parent = s;
      }
      p->right = s;
      s->parent = p;
      AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (r)));
      AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (p)));
    } else {
      p = r->left;
      r->left = p->right;
      if (p->right) {
        p->right->parent = r;
      }
      p->right = r;
      r->parent = p;
      s->right = p->left;
      if (p->left) {
        p->left->parent = s;
      }
      p->left = s;
      s->parent = p;
      AVL_SET_RANK (r, (AVL_GET_RANK (r) - AVL_GET_RANK (p)));
      AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (s)));
    }
    if (AVL_GET_BALANCE (p) == a) {
      AVL_SET_BALANCE (s, -a);
      AVL_SET_BALANCE (r, 0);
    } else if (AVL_GET_BALANCE (p) == -a) {
      AVL_SET_BALANCE (s, 0);
      AVL_SET_BALANCE (r, a);
    } else {
      AVL_SET_BALANCE (s, 0);
      AVL_SET_BALANCE (r, 0);
    }
    AVL_SET_BALANCE (p, 0);
      }
      /* finishing touch */
      if (s == t->right) {
    t->right = p;
      } else {
    t->left = p;
      }
      p->parent = t;
    }
  }
  return 0;
}