Ejemplo n.º 1
0
rbtree_node_t *rbtree_remove(rbtree_t *tree, rbtree_node_t *node)
{
  rbtree_node_t *remove, *child;
  if (node->left == tree->sentinel || node->right == tree->sentinel)
    remove = node;
  else
    remove = rbtree_successor(tree, node);
  if (remove->left != tree->sentinel)
    child = remove->left;
  else
    child = remove->right;

  child->parent = remove->parent;
  if (remove->parent == tree->sentinel)
    tree->root = child;
  else if (remove == remove->parent->left)
    remove->parent->left = child;
  else
    remove->parent->right = child;

  if (remove != node) {
    node->key = remove->key;
  }

  if (rbtree_is_black(remove))
    rbtree_remove_fixup(tree, child);
  rbtree_node_delete(remove);

  return node;
}
Ejemplo n.º 2
0
Archivo: rbt.c Proyecto: 1587/ltp
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--;
}