/************************************************************************ Add a new node to the tree, useful for data that is pre-sorted. @return appended node */ UNIV_INTERN const ib_rbt_node_t* rbt_add_node( /*=========*/ ib_rbt_t* tree, /*!< in: rb tree */ ib_rbt_bound_t* parent, /*!< in: bounds */ const void* value) /*!< in: this value is copied to the node */ { ib_rbt_node_t* node; /* Create the node that will hold the value data */ node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree)); memcpy(node->value, value, tree->sizeof_value); node->parent = node->left = node->right = tree->nil; /* If tree is empty */ if (parent->last == NULL) { parent->last = tree->root; } /* Append the node, the hope here is that the caller knows what s/he is doing. */ rbt_tree_add_child(tree, parent, node); rbt_balance_tree(tree, node); ++tree->n_nodes; #if defined(IB_RBT_TESTING) ut_a(rbt_validate(tree)); #endif return(node); }
/************************************************************************ Generic binary tree insert */ static ib_rbt_node_t* rbt_tree_insert( /*============*/ ib_rbt_t* tree, const void* key, ib_rbt_node_t* node) { ib_rbt_bound_t parent; ib_rbt_node_t* current = ROOT(tree); parent.result = 0; parent.last = tree->root; /* Regular binary search. */ while (current != tree->nil) { parent.last = current; parent.result = tree->compare(key, current->value); if (parent.result < 0) { current = current->left; } else { current = current->right; } } ut_a(current == tree->nil); rbt_tree_add_child(tree, &parent, node); return(node); }
/****************************************************************//** Add a new caller-provided node to tree at the specified position. The node must have its key fields initialized correctly. @return added node */ UNIV_INTERN const ib_rbt_node_t* rbt_add_preallocated_node( /*======================*/ ib_rbt_t* tree, /*!< in: rb tree */ ib_rbt_bound_t* parent, /*!< in: parent */ ib_rbt_node_t* node) /*!< in: node */ { node->parent = node->left = node->right = tree->nil; /* If tree is empty */ if (parent->last == NULL) { parent->last = tree->root; } /* Append the node, the hope here is that the caller knows what s/he is doing. */ rbt_tree_add_child(tree, parent, node); rbt_balance_tree(tree, node); ++tree->n_nodes; #if defined(IB_RBT_TESTING) ut_a(rbt_validate(tree)); #endif return(node); }
/************************************************************************ Merge the node from dst into src. Return the number of nodes merged. Delete the nodes from src after copying node to dst. As a side effect the duplicates will be left untouched in the src. @return no. of recs merged */ UNIV_INTERN ulint rbt_merge_uniq_destructive( /*=======================*/ ib_rbt_t* dst, /*!< in: dst rb tree */ ib_rbt_t* src) /*!< in: src rb tree */ { ib_rbt_bound_t parent; ib_rbt_node_t* src_node; ulint old_size = rbt_size(dst); if (rbt_empty(src) || dst == src) { return(0); } for (src_node = (ib_rbt_node_t*) rbt_first(src); src_node; /* */) { ib_rbt_node_t* prev = src_node; src_node = (ib_rbt_node_t*)rbt_next(src, prev); /* Skip duplicates. */ if (rbt_search(dst, &parent, prev->value) != 0) { /* Remove and reset the node but preserve the node (data) value. */ rbt_remove_node_and_rebalance(src, prev); /* The nil should be taken from the dst tree. */ prev->parent = prev->left = prev->right = dst->nil; rbt_tree_add_child(dst, &parent, prev); rbt_balance_tree(dst, prev); ++dst->n_nodes; } } #if defined(IB_RBT_TESTING) ut_a(rbt_validate(dst)); ut_a(rbt_validate(src)); #endif return(rbt_size(dst) - old_size); }