예제 #1
0
/* Inserts the given NODE into BT.
   Returns a null pointer if successful.
   Returns the existing node already in BT equal to NODE, on
   failure. */
static struct Node *insert(TreeMap *bt, struct Node *node,void *ExtraArgs)
{
  size_t depth = 0;

  node->down[0] = NULL;
  node->down[1] = NULL;

  if (bt->root == NULL) {
      bt->root = node;
      node->up = NULL;
    }
  else {
      struct Node *p = bt->root;
      for (;;) {
          int cmp, dir;

    	  cmp = bt->compare(node->data, p->data, ExtraArgs);
          if (cmp == 0)
            return p;
          depth++;

          dir = cmp > 0;
          if (p->down[dir] == NULL)
            {
              p->down[dir] = node;
              node->up = p;
              break;
            }
          p = p->down[dir];
        }
    }

  bt->count++;
  if (bt->count > bt->max_size)
    bt->max_size = bt->count;
  if (depth > calculate_h_alpha (bt->count)) {
      /* We use the "alternative" method of finding a scapegoat
         node described by Galperin and Rivest. */
      struct Node *s = node;
      size_t size = 1;
      size_t i;

      for (i = 1; ; i++)
        if (i < depth) {
            size += 1 + count_nodes_in_subtree (sibling (s));
            s = s->up;
            if (i > calculate_h_alpha (size)) {
                rebalance_subtree (bt, s, size);
                break;
              }
          }
        else {
            rebalance_subtree (bt, bt->root, bt->count);
            bt->max_size = bt->count;
            break;
          }
    }
    bt->timestamp++;
  return NULL;
}
예제 #2
0
파일: bt.c 프로젝트: RobertDash/pspp
/* Deletes P from BT. */
void
bt_delete (struct bt *bt, struct bt_node *p)
{
  struct bt_node **q = down_link (bt, p);
  struct bt_node *r = p->down[1];
  if (r == NULL)
    {
      *q = p->down[0];
      if (*q)
        (*q)->up = p->up;
    }
  else if (r->down[0] == NULL)
    {
      r->down[0] = p->down[0];
      *q = r;
      r->up = p->up;
      if (r->down[0] != NULL)
        r->down[0]->up = r;
    }
  else
    {
      struct bt_node *s = r->down[0];
      while (s->down[0] != NULL)
        s = s->down[0];
      r = s->up;
      r->down[0] = s->down[1];
      s->down[0] = p->down[0];
      s->down[1] = p->down[1];
      *q = s;
      if (s->down[0] != NULL)
        s->down[0]->up = s;
      s->down[1]->up = s;
      s->up = p->up;
      if (r->down[0] != NULL)
        r->down[0]->up = r;
    }
  bt->size--;

  /* We approximate .707 as .75 here.  This is conservative: it
     will cause us to do a little more rebalancing than strictly
     necessary to maintain the scapegoat tree's height
     invariant. */
  if (bt->size < bt->max_size * 3 / 4 && bt->size > 0)
    {
      rebalance_subtree (bt, bt->root, bt->size);
      bt->max_size = bt->size;
    }
}
예제 #3
0
/* Deletes P from BT. */
static void Delete(TreeMap *bt, struct Node *p)
{
  struct Node **q = down_link (bt, p);
  struct Node *r = p->down[1];
  if (r == NULL) {
      *q = p->down[0];
      if (*q)
        (*q)->up = p->up;
    }
  else if (r->down[0] == NULL) {
      r->down[0] = p->down[0];
      *q = r;
      r->up = p->up;
      if (r->down[0] != NULL)
        r->down[0]->up = r;
    }
  else {
      struct Node *s = r->down[0];
      while (s->down[0] != NULL)
        s = s->down[0];
      r = s->up;
      r->down[0] = s->down[1];
      s->down[0] = p->down[0];
      s->down[1] = p->down[1];
      *q = s;
      if (s->down[0] != NULL)
        s->down[0]->up = s;
      s->down[1]->up = s;
      s->up = p->up;
      if (r->down[0] != NULL)
        r->down[0]->up = r;
    }
  bt->count--;

  /* We approximate .707 as .75 here.  This is conservative: it
     will cause us to do a little more rebalancing than strictly
     necessary to maintain the scapegoat tree's height
     invariant. */
  if (bt->count < bt->max_size * 3 / 4 && bt->count > 0)
    {
      rebalance_subtree (bt, bt->root, bt->count);
      bt->max_size = bt->count;
    }
	if (bt->DestructorFn)
		bt->DestructorFn(p);
    iHeap.AddToFreeList(bt->Heap,p);
    bt->timestamp++;
}
예제 #4
0
   static void rebalance_after_insertion
      ( node_ptr x, std::size_t depth
      , std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
   {
      if(tree_size > max_tree_size)
         max_tree_size = tree_size;

      if(tree_size != 1 && depth > h_alpha(tree_size)){
         //Find the first non height-balanced node
         //as described in the section 4.2 of the paper.
         //This method is the alternative method described
         //in the paper. Authors claim that this method
         //may tend to yield more balanced trees on the average
         //than the weight balanced method.
         node_ptr s = x;
         std::size_t size = 1;

         for(std::size_t i = 1; true; ++i){
            bool rebalance = false;
            if(i == depth){
               BOOST_INTRUSIVE_INVARIANT_ASSERT(tree_size == count(s));
               rebalance = true;
            }
            else if(i > h_alpha(size)){
               node_ptr s_parent = NodeTraits::get_parent(s);
               node_ptr s_parent_left = NodeTraits::get_left(s_parent);
               size += 1 + tree_algorithms::count
                  ( s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left );
               s = s_parent;
               rebalance = true;
            }
            if(rebalance){
               rebalance_subtree(s);
               break;
            }
         }
      }
   }
예제 #5
0
파일: bt.c 프로젝트: RobertDash/pspp
/* Inserts the given NODE into BT.
   Returns a null pointer if successful.
   Returns the existing node already in BT equal to NODE, on
   failure. */
struct bt_node *
bt_insert (struct bt *bt, struct bt_node *node)
{
  int depth = 0;

  node->down[0] = NULL;
  node->down[1] = NULL;

  if (bt->root == NULL)
    {
      bt->root = node;
      node->up = NULL;
    }
  else
    {
      struct bt_node *p = bt->root;
      for (;;)
        {
          int cmp, dir;

          cmp = bt->compare (node, p, bt->aux);
          if (cmp == 0)
            return p;
          depth++;

          dir = cmp > 0;
          if (p->down[dir] == NULL)
            {
              p->down[dir] = node;
              node->up = p;
              break;
            }
          p = p->down[dir];
        }
    }

  bt->size++;
  if (bt->size > bt->max_size)
    bt->max_size = bt->size;

  if (depth > calculate_h_alpha (bt->size))
    {
      /* We use the "alternative" method of finding a scapegoat
         node described by Galperin and Rivest. */
      struct bt_node *s = node;
      size_t size = 1;
      int i;

      for (i = 1; ; i++)
        if (i < depth)
          {
            size += 1 + count_nodes_in_subtree (sibling (s));
            s = s->up;
            if (i > calculate_h_alpha (size))
              {
                rebalance_subtree (bt, s, size);
                break;
              }
          }
        else
          {
            rebalance_subtree (bt, bt->root, bt->size);
            bt->max_size = bt->size;
            break;
          }
    }

  return NULL;
}