Example #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;
}
Example #2
0
static void _rbtree_print(rbtree_t *tree, rbtree_node_t *node)
{
  if (node != tree->sentinel) {
    _rbtree_print(tree, node->left);
    printf("%d[%c] ", node->key, rbtree_is_black(node) ? 'b' : 'r');
    _rbtree_print(tree, node->right);
  }
}
Example #3
0
static void rbtree_remove_fixup(rbtree_t *tree, rbtree_node_t *node)
{
  rbtree_node_t *brother;
  while (node != tree->root && rbtree_is_black(node)) {
    if (node == node->parent->left) {
      brother = node->parent->right;
      if (rbtree_is_red(brother)) {
	rbtree_color_swap(node->parent, brother);
	rbtree_left_rotate(tree, node->parent);
	brother = node->parent->right;
      }
      if (rbtree_is_black(brother->left) &&
	  rbtree_is_black(brother->right)) {
	rbtree_set_red(brother);
	node = node->parent;
      } else {
	if (rbtree_is_black(brother->right)) {
	  rbtree_color_swap(brother, brother->left);
	  rbtree_right_rotate(tree, brother);
	  brother = node->parent->right;
	}
	rbtree_set_black(brother->right);
	rbtree_color_swap(node->parent, brother);
	rbtree_left_rotate(tree, node->parent);
	node = tree->root;
      }
    } else {
      brother = node->parent->left;
      if (rbtree_is_red(brother)) {
	rbtree_color_swap(node->parent, brother);
	rbtree_right_rotate(tree, node->parent);
	brother = node->parent->left;
      }
      if (rbtree_is_black(brother->left) &&
	  rbtree_is_black(brother->right)) {
	rbtree_set_red(brother);
	node = node->parent;
      } else {
	if (rbtree_is_black(brother->left)) {
	  rbtree_color_swap(brother, brother->right);
	  rbtree_left_rotate(tree, brother);
	  brother = node->parent->left;
	}
	rbtree_set_black(brother->left);
	rbtree_color_swap(node->parent, brother);
	rbtree_right_rotate(tree, node->parent);
	node = tree->root;
      }
    }
  }
  rbtree_set_black(node);
}
Example #4
0
void
rbtree_delete(struct rbtree *tree, struct rbnode *node)
{
    struct rbnode **root = &tree->root;
    struct rbnode *sentinel = tree->sentinel;
    struct rbnode *subst, *temp, *w;
    uint8_t red;

    /* a binary tree delete */

    if (node->left == sentinel) {
        temp = node->right;
        subst = node;
    } else if (node->right == sentinel) {
        temp = node->left;
        subst = node;
    } else {
        subst = rbtree_node_min(node->right, sentinel);
        if (subst->left != sentinel) {
            temp = subst->left;
        } else {
            temp = subst->right;
        }
    }

    if (subst == *root) {
        *root = temp;
        rbtree_black(temp);

        rbtree_node_init(node);

        return;
    }

    red = rbtree_is_red(subst);

    if (subst == subst->parent->left) {
        subst->parent->left = temp;
    } else {
        subst->parent->right = temp;
    }

    if (subst == node) {
        temp->parent = subst->parent;
    } else {

        if (subst->parent == node) {
            temp->parent = subst;
        } else {
            temp->parent = subst->parent;
        }

        subst->left = node->left;
        subst->right = node->right;
        subst->parent = node->parent;
        rbtree_copy_color(subst, node);

        if (node == *root) {
            *root = subst;
        } else {
            if (node == node->parent->left) {
                node->parent->left = subst;
            } else {
                node->parent->right = subst;
            }
        }

        if (subst->left != sentinel) {
            subst->left->parent = subst;
        }

        if (subst->right != sentinel) {
            subst->right->parent = subst;
        }
    }

    rbtree_node_init(node);

    if (red) {
        return;
    }

    /* a delete fixup */

    while (temp != *root && rbtree_is_black(temp)) {

        if (temp == temp->parent->left) {
            w = temp->parent->right;

            if (rbtree_is_red(w)) {
                rbtree_black(w);
                rbtree_red(temp->parent);
                rbtree_left_rotate(root, sentinel, temp->parent);
                w = temp->parent->right;
            }

            if (rbtree_is_black(w->left) && rbtree_is_black(w->right)) {
                rbtree_red(w);
                temp = temp->parent;
            } else {
                if (rbtree_is_black(w->right)) {
                    rbtree_black(w->left);
                    rbtree_red(w);
                    rbtree_right_rotate(root, sentinel, w);
                    w = temp->parent->right;
                }

                rbtree_copy_color(w, temp->parent);
                rbtree_black(temp->parent);
                rbtree_black(w->right);
                rbtree_left_rotate(root, sentinel, temp->parent);
                temp = *root;
            }

        } else {
            w = temp->parent->left;

            if (rbtree_is_red(w)) {
                rbtree_black(w);
                rbtree_red(temp->parent);
                rbtree_right_rotate(root, sentinel, temp->parent);
                w = temp->parent->left;
            }

            if (rbtree_is_black(w->left) && rbtree_is_black(w->right)) {
                rbtree_red(w);
                temp = temp->parent;
            } else {
                if (rbtree_is_black(w->left)) {
                    rbtree_black(w->right);
                    rbtree_red(w);
                    rbtree_left_rotate(root, sentinel, w);
                    w = temp->parent->left;
                }

                rbtree_copy_color(w, temp->parent);
                rbtree_black(temp->parent);
                rbtree_black(w->left);
                rbtree_right_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        }
    }

    rbtree_black(temp);
}