/* 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; }
/* 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; } }
/* 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++; }
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; } } } }
/* 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; }