/** * Split a range into 3 parts to accommodate a tree-node * @param d the dom in question * @param n the node in the tree * @param r the out of tree range r to split up */ static void dom_breakup_range( dom *d, node *n, node *r ) { node *r2; if ( node_offset(n) > node_offset(r) ) { node_split( r, node_offset(n) ); r2 = node_next_sibling( r ); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r) ); //queue_push( d->q, node_to_range(r) ); node_dispose( r ); } else r2 = r; if ( node_end(r2)>node_end(n) ) { node *r3; node_split( r2, node_end(n) ); r3 = node_next_sibling(r2); node_detach_sibling(r3,r2); dom_store_range( d, node_to_range(r3) ); //queue_push( d->q, node_to_range(r3) ); node_dispose(r3); } dom_node_equals( d, n, r2 ); }
/** * Try to make the new node into a parent of the tree-node n. The problem * here is that we must include any siblings of n in r if they fit. * @param n the node above which to add the parent * @param r the new unattached node */ static void dom_make_parent( dom *d, node *n, node *r ) { node *parent = node_parent(n); node *prev = node_prec_sibling( n ); if ( parent==NULL ) printf("parent is NULL\n"); //fprintf( stderr,"n: %s %d:%d; r %s %d:%d\n",node_name(n),node_offset(n), // node_end(n),node_name(r),node_offset(r),node_end(r)); //node_debug_check_siblings( node_first_child(parent) ); while ( n != NULL && !node_follows(r,n) ) { node *next = node_next_sibling(n); if ( dom_nests(d,node_name(n),node_name(r)) ) { if ( range_encloses_node(n,r) || range_equals_node(n,r) ) { node_detach_sibling( n, prev ); node_add_child( r, n ); if ( node_overlaps_on_right(parent,r) ) { node_split( r, node_end(parent) ); node *r2 = node_next_sibling( r ); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r2) ); node_dispose( r2 ); } } else if ( node_overlaps_on_left(n,r) ) { node_split( n, node_end(r) ); node_detach_sibling( n, prev ); node_add_child( r, n ); break; } else break; } else { // split off the rest of r and and push it back // Q: what happens to r?? node *r2; node_split( r, node_offset(n) ); r2 = node_next_sibling( r ); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r2) ); //queue_push( d->q, node_to_range(r2) ); node_dispose( r2 ); break; } n = next; if ( n != NULL ) prev = node_prec_sibling( n ); } // make n's original parent the parent of r node_add_child( parent, r ); // node_debug_check_siblings( node_first_child(parent) ); }
/** * Split a node into 3 parts to accommodate a range * @param d the dom in question * @param n the node in the tree to split up * @param r the out of tree node r that overlaps with n */ static void dom_breakup_node( dom *d, node *n, node *r ) { node *n2; if ( node_offset(r) > node_offset(n) ) { node_split( n, node_offset(r) ); n2 = node_next_sibling( n ); } else n2 = n; if ( node_end(r) < node_end(n2) ) node_split( n2, node_end(r) ); dom_node_equals( d, n2, r ); }
static node_t *node_put(tree_t *tree, node_t *p, node_t *child) { if (IS_NIL(p)) p = child; else { int d = tree->compare(child->key, p->key); if (d == 0) return NULL; if (d < 0) { node_t *q = node_put(tree, p->left, child); if (!q) return NULL; p->left = q; } else { node_t *q = node_put(tree, p->right, child); if (!q) return NULL; p->right = q; } p = node_split(node_skew(p)); } return p; }
static node_t *node_rebalance(node_t *p) { if ((p->left->level < (p->level - 1)) || (p->right->level < (p->level - 1))) { if (p->right->level > --p->level) p->right->level = p->level; p = node_skew(p); p->right = node_skew(p->right); p->right->right = node_skew(p->right->right); p = node_split(p); p->right = node_split(p->right); } return p; }
static value_t *find_below(hattrie_t *T, node_ptr parent, const char *key, size_t len) { /* consume all trie nodes, now parent must be trie and child anything */ node_ptr node = hattrie_consume(&parent, &key, &len, 0); assert(*parent.flag & NODE_TYPE_TRIE); /* if the key has been consumed on a trie node, use its value */ if (len == 0) { if (*node.flag & NODE_TYPE_TRIE) { return hattrie_useval(T, node); } else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) { return hattrie_useval(T, parent); } } #ifdef HHASH_MAX_FILL /* preemptively split the bucket if fill is over threshold */ if (node.b->weight >= node.b->size * HHASH_MAX_FILL) { node_split(T, parent, node); return find_below(T, parent, key, len); } #endif /* attempt to fit new element and split if it doesn't fit */ value_t *val = NULL; assert(len > 0); if (*node.flag & NODE_TYPE_PURE_BUCKET) { val = hhash_map(node.b, key + 1, len - 1, HHASH_INSERT); } else { val = hhash_map(node.b, key, len, HHASH_INSERT); } /* not inserted, recursively split */ if (val == NULL) { node_split(T, parent, node); val = find_below(T, parent, key, len); } return val; }
/** * Handle overlap on the right of a tree-node * @param d the dom in question * @param n the node to test against * @param r the rogue who overlaps on the right */ static void dom_range_overlaps_right( dom *d, node *n, node *r ) { if ( dom_mostly_nests(d,node_name(n),node_name(r)) ) { node_split( n, node_offset(r) ); dom_add_node( d, node_next_sibling(n), r ); } else if ( dom_mostly_nests(d,node_name(r),node_name(n)) ) { node *r2; node_split( r, node_end(n) ); r2 = node_next_sibling(r); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r2) ); //queue_push( d->q, node_to_range(r2) ); node_dispose( r2 ); dom_add_node( d, n, r ); } else dom_drop_notify( d, r, n ); }
/** * Extend the implicit suffix tree by adding one suffix of the current prefix * @param st the current suffixtree * @param j the offset into str of the suffix's start * @param i the offset into str at the end of the current prefix * @param log the log to record errors in * @return 1 if the phase continues else 0 */ static int extension( suffixtree *st, int j, int i, plugin_log *log ) { int res = 1; pos *p = find_beta( st, j, i-1, log ); // rule 1 (once a leaf always a leaf) if ( node_is_leaf(p->v) && pos_at_edge_end(st,p) ) res = 1; // rule 2 else if ( !continues(st,p,st->str[i]) ) { //printf("applying rule 2 at j=%d for phase %d\n",j,i); node *leaf = node_create_leaf( i, log ); if ( p->v==st->root || pos_at_edge_end(st,p) ) { node_add_child( p->v, leaf, st->str, log ); update_current_link( st, p->v ); } else { node *u = node_split( p->v, p->loc, st->str, log ); update_current_link( st, u ); if ( i-j==1 ) { node_set_link( u, st->root ); #ifdef DEBUG verify_link( current ); #endif } else st->current = u; node_add_child( u, leaf, st->str, log ); } update_old_beta( st, p, i ); } // rule 3 else { //printf("applying rule 3 at j=%d for phase %d\n",j,i); update_current_link( st, p->v ); update_old_beta( st, p, i ); res = 0; } free( p ); return res; }
/** * Extend the implicit suffix tree by adding one suffix of the current prefix * @param j the offset into str of the suffix's start * @param i the offset into str at the end of the current prefix * @return 1 if the phase continues else 0 */ static int extension( int j, int i ) { int res = 1; pos *p = find_beta( j, i-1 ); // rule 1 (once a leaf always a leaf) if ( node_is_leaf(p->v) && pos_at_edge_end(p) ) res = 1; // rule 2 else if ( !continues(p,str[i]) ) { //printf("applying rule 2 at j=%d for phase %d\n",j,i); node *leaf = node_create_leaf( i ); if ( p->v==root || pos_at_edge_end(p) ) { node_add_child( p->v, leaf ); update_current_link( p->v ); } else { node *u = node_split( p->v, p->loc ); update_current_link( u ); if ( i-j==1 ) { node_set_link( u, root ); #ifdef DEBUG verify_link( current ); #endif } else current = u; node_add_child( u, leaf ); } update_old_beta( p, i ); } // rule 3 else { //printf("applying rule 3 at j=%d for phase %d\n",j,i); update_current_link( p->v ); update_old_beta( p, i ); res = 0; } free( p ); return res; }
void btree_insert_at(btree_iterator iter, const void *item) { const void *x = item; struct btree_node *xr = NULL; struct btree_node *p; struct btree *btree = iter->btree; /* btree_insert_at always sets iter->item to item. */ iter->item = (void*)item; /* * If node is not a leaf, fall to the end of the left branch of item[k] * so that it will be a leaf. This does not modify the iterator's logical * position. */ if (iter->node->depth) branch_end(iter); /* * First try inserting item into this node. * If it's too big, split it, and repeat by * trying to insert the median and right subtree into parent. */ if (iter->node->count < MAX) { node_insert(x, xr, iter->node, iter->k); goto finished; } else { for (;;) { node_split(&x, &xr, iter->node, iter->k); if (!ascend(iter)) break; if (iter->node->count < MAX) { node_insert(x, xr, iter->node, iter->k); goto finished; } } /* * If splitting came all the way up to the root, create a new root whose * left branch is the current root, median is x, and right branch is the * half split off from the root. */ assert(iter->node == btree->root); p = node_alloc(1); p->parent = NULL; p->count = 1; p->depth = btree->root->depth + 1; p->item[0] = x; p->branch[0] = btree->root; btree->root->parent = p; btree->root->k = 0; p->branch[1] = xr; xr->parent = p; xr->k = 1; btree->root = p; } finished: btree->count++; iter->node = NULL; }