rb_node *insert_successor_at(rb_tree * tree, rb_node * at_node, datatype object) { rb_node *parent; rb_node *new_node; if (!(tree->root)) { /* Assign a new root node (the root is always * black) */ new_node = rbnode_construct(object, black); if (!new_node) return NULL; tree->root = new_node; tree->isize = 1; return new_node; } /* Insert the new object as a red leaf, being the successor of * node */ new_node = rbnode_construct(object, red); if (!new_node) return NULL; if (!at_node) { /* The new node should become the tree's minimum Place * is as the left child of the current minimal leaf */ parent = rbnode_minimum(tree->root); parent->left = new_node; } else { /* Make sure the insertion does not violate the tree * order In case given node has no right child, place * the new node as its right child. Otherwise, place * it at the leftmost position at the sub-tree rooted * at its right side. */ if (!at_node->right) { parent = at_node; parent->right = new_node; } else { parent = rbnode_minimum(at_node->right); parent->left = new_node; } } new_node->parent = parent; /* Mark that a new node was added */ tree->isize++; /* Fix the tree properties */ rbtree_insert_fixup(tree, new_node); return new_node; }
/*! * Get the next node in the tree (according to the tree order) * * [takes O(log n) operations at worst-case, but only O(1) amortized] * * \param tree The tree * * \param node The current object * * \return The successor node, or a NULL, if we are at the tree maximum */ rbnode_t * rbtree_successor ( rbtree_t *tree, rbnode_t *node ) { rbnode_t *succ; /* * If there is a right child, the successor is the minimal * object in the sub-tree spanned by this child. */ if (node->right != NULL) return rbnode_minimum(node->right); /* * Otherwise, go up the tree until reaching the parent * from the left direction. */ succ = node->parent; while (succ != NULL && node == succ->right) { node = succ; succ = succ->parent; } return succ; }
rb_node *rbtree_minimum(rb_tree * tree) { if (!(tree->root)) return NULL; /* Return the leftmost leaf in the tree */ return rbnode_minimum(tree->root); }
void rbtree_remove_at(rb_tree * tree, rb_node * node, destructor d) { rb_node *child = NULL; /* In case of deleting the single object stored in the tree, * free the root, thus emptying the tree */ if (tree->isize == 1) { rbnode_destruct(tree->root, d); tree->root = NULL; tree->isize = 0; return; } /* Remove the given node from the tree */ if (node->left && node->right) { /* If the node we want to remove has two children, * find its successor, which is the leftmost child in * its right sub-tree and has at most one child (it * may have a right child). */ rb_node *succ_node = rbnode_minimum(node->right); /* Now physically swap node and its successor. Notice * this may temporarily violate the tree properties, * but we are going to remove node anyway. This way * we have moved node to a position were it is more * convinient to delete it. */ int immediate_succ = (node->right == succ_node); rb_node *succ_parent = succ_node->parent; rb_node *succ_left = succ_node->left; rb_node *succ_right = succ_node->right; rb_color succ_color = succ_node->color; succ_node->parent = node->parent; succ_node->left = node->left; succ_node->right = immediate_succ ? node : node->right; succ_node->color = node->color; node->parent = immediate_succ ? succ_node : succ_parent; node->left = succ_left; node->right = succ_right; node->color = succ_color; if (!immediate_succ) { if (succ_node == node->parent->left) node->parent->left = node; else node->parent->right = node; } if (node->left) node->left->parent = node; if (node->right) node->right->parent = node; if (succ_node->parent) { if (node == succ_node->parent->left) succ_node->parent->left = succ_node; else succ_node->parent->right = succ_node; } else { tree->root = succ_node; } if (succ_node->left) succ_node->left->parent = succ_node; if (succ_node->right) succ_node->right->parent = succ_node; } /* At this stage, the node we are going to remove has at most * one child */ child = (node->left) ? node->left : node->right; /* Splice out the node to be removed, by linking its parent * straight to the removed node's single child. */ if (child) child->parent = node->parent; if (!(node->parent)) { /* If we are deleting the root, make the child the new * tree node */ tree->root = child; } else { /* Link the removed node parent to its child */ if (node == node->parent->left) node->parent->left = child; else node->parent->right = child; } /* Fix-up the red-black properties that may have been damaged: * If we have just removed a black node, the black-depth * property is no longer valid */ if (node->color == black && child) rbtree_remove_fixup(tree, child); /* Delete the un-necessary node (nullify both its children * because the node's destructor is recursive). */ node->left = NULL; node->right = NULL; free(node); /* Decrease the number of objects in the tree */ tree->isize--; }
/*! * Insert a new object to the tree as the a successor of a given node * * \param tree The tree * * \return The new node */ rbnode_t * rbtree_insert_successor_object_at ( rbtree_t * tree, rbnode_t * at_node, void * object ) { rbnode_t * parent; rbnode_t * new_node; if (!(tree->root)) { /* Assign a new root node. * Notice that the root is always black */ new_node = rbnode_create(object, RB_BLACK); if (!new_node) return NULL; tree->root = new_node; tree->size = 1; new_node->tree = tree; return new_node; } /* Insert the new object as a red leaf, being the successor of node */ new_node = rbnode_create(object, RB_RED); if (!new_node) return NULL; if (!at_node) { /* * The new node should become the tree minimum: Place is as the left * child of the current minimal leaf. */ parent = rbnode_minimum(tree->root); parent->left = new_node; } else { /* Make sure the insertion does not violate the tree order */ /* * In case given node has no right child, place the new node as its * right child. Otherwise, place it at the leftmost position at the * sub-tree rooted at its right side. */ if (!at_node->right) { parent = at_node; parent->right = new_node; } else { parent = rbnode_minimum(at_node->right); parent->left = new_node; } } new_node->parent = parent; /* Mark that a new node was added */ tree->size++; /* Fix up the tree properties */ rbtree_insert_fixup(tree, new_node); new_node->tree = tree; return new_node; }