/**
 * Delete a node from one order of a red-black tree
 *
 * This function has three parameters: a tree, the node to delete, and
 * the order from which to delete it.  _rb_delete() is an
 * implementation of the routine RB-DELETE on p. 273 of Cormen et
 * al. (p. 324 in the paperback version of the 2009 edition).
 */
HIDDEN void
_rb_delete(struct bu_rb_tree *tree, struct bu_rb_node *node, int order)
{
    struct bu_rb_node *y;		/* The node to splice out */
    struct bu_rb_node *parent;
    struct bu_rb_node *only_child;

    BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
    BU_CKMAG(node, BU_RB_NODE_MAGIC, "red-black node");
    RB_CKORDER(tree, order);

    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_DELETE))
	bu_log("_rb_delete(%p, %p, %d): data=%p\n",
	       (void*)tree, (void*)node, order, RB_DATA(node, order));

    if ((RB_LEFT_CHILD(node, order) == RB_NULL(tree))
	|| (RB_RIGHT_CHILD(node, order) == RB_NULL(tree)))
	y = node;
    else
	y = rb_neighbor(node, order, SENSE_MAX);

    if (RB_LEFT_CHILD(y, order) == RB_NULL(tree))
	only_child = RB_RIGHT_CHILD(y, order);
    else
	only_child = RB_LEFT_CHILD(y, order);

    parent = RB_PARENT(only_child, order) = RB_PARENT(y, order);
    if (parent == RB_NULL(tree))
	RB_ROOT(tree, order) = only_child;
    else if (y == RB_LEFT_CHILD(parent, order))
	RB_LEFT_CHILD(parent, order) = only_child;
    else
	RB_RIGHT_CHILD(parent, order) = only_child;

    /*
     * Splice y out if it's not node
     */
    if (y != node) {
	(node->rbn_package)[order] = (y->rbn_package)[order];
	((node->rbn_package)[order]->rbp_node)[order] = node;
    }

    if (RB_GET_COLOR(y, order) == RB_BLK)
	_rb_fixup(tree, only_child, order);

    if (--(y->rbn_pkg_refs) == 0)
	rb_free_node(y);
}
Exemplo n.º 2
0
/*
 * Recreate the addr tree of vm_map in local memory.
 */
struct vm_map_entry *
load_vm_map_entries(kvm_t *kd, struct vm_map_entry *kptr,
    struct vm_map_entry *parent)
{
	static struct kbit map_ent;
	struct vm_map_entry *result;

	if (kptr == NULL)
		return NULL;

	A(&map_ent) = (u_long)kptr;
	S(&map_ent) = sizeof(struct vm_map_entry);
	KDEREF(kd, &map_ent);

	result = malloc(sizeof(*result));
	if (result == NULL)
		err(1, "malloc");
	memcpy(result, D(&map_ent, vm_map_entry), sizeof(struct vm_map_entry));

	/*
	 * Recurse to download rest of the tree.
	 */
	RB_LEFT(result, daddrs.addr_entry) = load_vm_map_entries(kd,
	    RB_LEFT(result, daddrs.addr_entry), result);
	RB_RIGHT(result, daddrs.addr_entry) = load_vm_map_entries(kd,
	    RB_RIGHT(result, daddrs.addr_entry), result);
	RB_PARENT(result, daddrs.addr_entry) = parent;
	return result;
}
Exemplo n.º 3
0
/*
 * rb_successor - find the next node of node in ascending order.
 */
static void* rb_successor(void *node){
    void *succ, *left;
    if((succ = RB_RIGHT(node)) != rb_null){
        while((left = RB_LEFT(succ)) != rb_null){
            succ = left;
        }
        return succ;
    }else{
        succ = RB_PARENT(node);
        while(RB_RIGHT(succ) == node){
            node = succ;
            succ = RB_PARENT(succ);
        }
        if(succ == rb_root) return rb_null;
        return succ;
    }
}
Exemplo n.º 4
0
/* Note args swapped to match Linux */
void rb_insert_color(struct rb_node *elm, struct rb_root *head)
{
	struct rb_node *parent, *gparent, *tmp;
	while ((parent = RB_PARENT(elm)) &&
	    RB_COLOR(parent) == RB_RED) {
		gparent = RB_PARENT(parent);
		if (parent == RB_LEFT(gparent)) {
			tmp = RB_RIGHT(gparent);
			if (tmp && RB_COLOR(tmp) == RB_RED) {
				RB_COLOR(tmp) = RB_BLACK;
				RB_SET_BLACKRED(parent, gparent);
				elm = gparent;
				continue;
			}
			if (RB_RIGHT(parent) == elm) {
				RB_ROTATE_LEFT(head, parent, tmp);
				tmp = parent;
				parent = elm;
				elm = tmp;
			}
			RB_SET_BLACKRED(parent, gparent);
			RB_ROTATE_RIGHT(head, gparent, tmp);
		} else {
			tmp = RB_LEFT(gparent);
			if (tmp && RB_COLOR(tmp) == RB_RED) {
				RB_COLOR(tmp) = RB_BLACK;
				RB_SET_BLACKRED(parent, gparent);
				elm = gparent;
				continue;
			}
			if (RB_LEFT(parent) == elm) {
				RB_ROTATE_RIGHT(head, parent, tmp);
				tmp = parent;
				parent = elm;
				elm = tmp;
			}
			RB_SET_BLACKRED(parent, gparent);
			RB_ROTATE_LEFT(head, gparent, tmp);
		}
	}
	RB_COLOR(head->rb_node) = RB_BLACK;
}
void
rb_rot_left(struct bu_rb_node *x, int order)
{
    struct bu_rb_node *y;		/* x's child to pivot up */
    struct bu_rb_node *beta;		/* y's child in direction of rot. */
    struct bu_rb_node *x_parent;	/* x's parent */
    struct bu_rb_tree *tree = x->rbn_tree;	/* Tree where it all happens */

    /*
     * Set y and check data types of both x and y
     */
    BU_CKMAG(x, BU_RB_NODE_MAGIC, "red-black node");
    RB_CKORDER(x->rbn_tree, order);

    y = RB_RIGHT_CHILD(x, order);

    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_ROTATE))
	bu_log("rb_rot_left(<%p>, %d)...\n", (void*)x, order);

    RB_RIGHT_CHILD(x, order) = beta = RB_LEFT_CHILD(y, order);
    if (beta != RB_NULL(tree))
	RB_PARENT(beta, order) = x;
    RB_PARENT(y, order) = x_parent = RB_PARENT(x, order);
    if (x_parent == RB_NULL(tree))
	RB_ROOT(tree, order) = y;
    else if (x == RB_LEFT_CHILD(x_parent, order))
	RB_LEFT_CHILD(x_parent, order) = y;
    else
	RB_RIGHT_CHILD(x_parent, order) = y;
    RB_LEFT_CHILD(y, order) = x;
    RB_PARENT(x, order) = y;

    RB_SIZE(y, order) = RB_SIZE(x, order);
    RB_SIZE(x, order) =
	RB_SIZE(RB_LEFT_CHILD(x, order), order) +
	RB_SIZE(RB_RIGHT_CHILD(x, order), order) + 1;
    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_OS))
	bu_log("After rotation, size(%p, %d)=%d, size(%p, %d)=%d\n",
	       (void*)x, order, RB_SIZE(x, order), (void*)y, order, RB_SIZE(y, order));
}
Exemplo n.º 6
0
static void
wf2q_augment_func(struct bfq_thread_io *node)
{
	struct bfq_thread_io *tmp = node, *tmp2;
	int min_vd;
	do{
		min_vd = tmp->vd;
		tmp2 = RB_LEFT(tmp, entry);
		min_vd = tmp2 ? MIN(tmp2->min_vd, min_vd) : min_vd;
		tmp2 = RB_RIGHT(tmp, entry);
		min_vd = tmp2 ? MIN(tmp2->min_vd, min_vd) : min_vd;
		tmp->min_vd = min_vd;
	}while((tmp = RB_PARENT(tmp,entry)));
}
/**
 * Restore the red-black properties of a red-black tree after the
 * splicing out of a node
 *
 * This function has three parameters: the tree to be fixed up, the
 * node where the trouble occurs, and the order.  _rb_fixup() is an
 * implementation of the routine RB-DELETE-FIXUP on p. 274 of Cormen
 * et al. (p. 326 in the paperback version of the 2009 edition).
 */
HIDDEN void
_rb_fixup(struct bu_rb_tree *tree, struct bu_rb_node *node, int order)
{
    int direction;
    struct bu_rb_node *parent;
    struct bu_rb_node *w;

    BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
    BU_CKMAG(node, BU_RB_NODE_MAGIC, "red-black node");
    RB_CKORDER(tree, order);

    while ((node != RB_ROOT(tree, order))
	   && (RB_GET_COLOR(node, order) == RB_BLK))
    {
	parent = RB_PARENT(node, order);
	if (node == RB_LEFT_CHILD(parent, order))
	    direction = RB_LEFT;
	else
	    direction = RB_RIGHT;

	w = RB_OTHER_CHILD(parent, order, direction);
	if (RB_GET_COLOR(w, order) == RB_RED) {
	    RB_SET_COLOR(w, order, RB_BLK);
	    RB_SET_COLOR(parent, order, RB_RED);
	    RB_ROTATE(parent, order, direction);
	    w = RB_OTHER_CHILD(parent, order, direction);
	}
	if ((RB_GET_COLOR(RB_CHILD(w, order, direction), order) == RB_BLK)
	    && (RB_GET_COLOR(RB_OTHER_CHILD(w, order, direction), order) == RB_BLK))
	{
	    RB_SET_COLOR(w, order, RB_RED);
	    node = parent;
	} else {
	    if (RB_GET_COLOR(RB_OTHER_CHILD(w, order, direction), order) == RB_BLK) {
		RB_SET_COLOR(RB_CHILD(w, order, direction), order, RB_BLK);
		RB_SET_COLOR(w, order, RB_RED);
		RB_OTHER_ROTATE(w, order, direction);
		w = RB_OTHER_CHILD(parent, order, direction);
	    }
	    RB_SET_COLOR(w, order, RB_GET_COLOR(parent, order));
	    RB_SET_COLOR(parent, order, RB_BLK);
	    RB_SET_COLOR(RB_OTHER_CHILD(w, order, direction),
			 order, RB_BLK);
	    RB_ROTATE(parent, order, direction);
	    node = RB_ROOT(tree, order);
	}
    }
    RB_SET_COLOR(node, order, RB_BLK);
}
Exemplo n.º 8
0
/*
 * rb_rotate_right - rotate node and children of node to the right
 */
static void rb_rotate_right(void *node){
    void *left;

    left = RB_LEFT(node);
    RB_LEFT(node) = RB_RIGHT(left);
    if(RB_RIGHT(left) != rb_null)
        RB_PARENT(RB_RIGHT(left)) = node;

    RB_PARENT(left) = RB_PARENT(node);
    if(node == RB_LEFT(RB_PARENT(node))){
        RB_LEFT(RB_PARENT(node)) = left;
    }else{
        RB_RIGHT(RB_PARENT(node)) = left;
    }
    RB_RIGHT(left) = node;
    RB_PARENT(node) = left;
}
Exemplo n.º 9
0
/*
 * rb_rotate_left - rotate node and children of node to the left
 */
static void rb_rotate_left(void *node){
    void *right;

    right = RB_RIGHT(node);
    RB_RIGHT(node) = RB_LEFT(right);
    if(RB_LEFT(right) != rb_null)
        RB_PARENT(RB_LEFT(right)) = node;

    RB_PARENT(right) = RB_PARENT(node);
    if(node == RB_LEFT(RB_PARENT(node))){
        RB_LEFT(RB_PARENT(node)) = right;
    }else{
        RB_RIGHT(RB_PARENT(node)) = right;
    }
    RB_LEFT(right) = node;
    RB_PARENT(node) = right;
}
Exemplo n.º 10
0
static
VOID
LwRtlRBTreeInsert(
    PLWRTL_RB_TREE pRBTree,
    PLWRTL_RB_TREE_NODE pTreeNode
    )
{
    PLWRTL_RB_TREE_NODE pParent = pRBTree->pSentinel;
    PLWRTL_RB_TREE_NODE pCurrent = pRBTree->pRoot;

    while (!RB_IS_NIL(pRBTree, pCurrent))
    {
        pParent = pCurrent;

        if (pRBTree->pfnCompare(pTreeNode->pKey, pCurrent->pKey) < 0)
        {
            pCurrent = pCurrent->pLeft;
        }
        else
        {
            pCurrent = pCurrent->pRight;
        }
    }

    RB_SET_PARENT(pTreeNode, pParent);

    if (RB_IS_NIL(pRBTree, RB_PARENT(pTreeNode)))
    {
        pRBTree->pRoot = pTreeNode;
    }
    else
    {
        if (pRBTree->pfnCompare(pTreeNode->pKey, pParent->pKey) < 0)
        {
            pParent->pLeft = pTreeNode;
        }
        else
        {
            pParent->pRight = pTreeNode;
        }
    }
}
Exemplo n.º 11
0
struct rb_node *rb_prev(struct rb_node *elm)
{
	if (RB_LEFT(elm)) {
		elm = RB_LEFT(elm);
		while (RB_RIGHT(elm))
			elm = RB_RIGHT(elm);
	} else {
		if (RB_PARENT(elm) &&
		    (elm == RB_RIGHT(RB_PARENT(elm))))
			elm = RB_PARENT(elm);
		else {
			while (RB_PARENT(elm) &&
			    (elm == RB_LEFT(RB_PARENT(elm))))
				elm = RB_PARENT(elm);
			elm = RB_PARENT(elm);
		}
	}
	return (elm);
}
Exemplo n.º 12
0
static
VOID
LwRtlRBTreeFixColors(
    PLWRTL_RB_TREE     pRBTree,
    PLWRTL_RB_TREE_NODE pTreeNode
    )
{
    PLWRTL_RB_TREE_NODE pUncle = NULL;
    PLWRTL_RB_TREE_NODE pParent = NULL;
    PLWRTL_RB_TREE_NODE pGrandParent = NULL;

    while ((pRBTree->pRoot != pTreeNode) && RB_IS_BLACK(pTreeNode))
    {
        pParent = RB_PARENT(pTreeNode);
        pGrandParent = RB_PARENT(pParent);

        if (pTreeNode == pParent->pLeft)
        {
             pUncle = pParent->pRight;

            if (!RB_IS_NIL(pRBTree, pUncle) && RB_IS_RED(pUncle))
            {
                RB_COLOR_BLACK(pUncle);
                RB_COLOR_RED(pParent);
                LwRtlRBTreeRotateLeft(pRBTree, pParent);
                pUncle = pParent->pRight;
            }

            if (!RB_IS_NIL(pRBTree, pUncle) &&
                RB_IS_BLACK(pUncle->pLeft) && RB_IS_BLACK(pUncle->pRight))
            {
                RB_COLOR_RED(pUncle);
                pTreeNode = pParent;
                continue;
            }

            if (!RB_IS_NIL(pRBTree, pUncle) && RB_IS_BLACK(pUncle->pRight))
            {
                RB_COLOR_BLACK(pUncle->pLeft);
                RB_COLOR_RED(pUncle);

                LwRtlRBTreeRotateRight(pRBTree, pUncle);
                pUncle = pParent->pRight;
            }

            if (!RB_IS_NIL(pRBTree, pUncle))
            {
                RB_COPY_COLOR(pUncle, pParent);
            }
            RB_COLOR_BLACK(pParent);
            if (!RB_IS_NIL(pRBTree, pUncle))
            {
                RB_COLOR_BLACK(pUncle->pRight);
                LwRtlRBTreeRotateLeft(pRBTree, pParent);
            }
            pTreeNode = pRBTree->pRoot;
        }
        else
        {
            pUncle = pParent->pLeft;

            if (!RB_IS_NIL(pRBTree, pUncle) && RB_IS_RED(pUncle))
            {
                RB_COLOR_BLACK(pUncle);
                RB_COLOR_RED(pParent);
                LwRtlRBTreeRotateRight(pRBTree, pParent);
                pUncle = pParent->pLeft;
            }

            if (!RB_IS_NIL(pRBTree, pUncle) &&
                 RB_IS_BLACK(pUncle->pLeft) && RB_IS_BLACK(pUncle->pRight))
            {
                RB_COLOR_RED(pUncle);
                pTreeNode = pParent;
                continue;
            }

            if (!RB_IS_NIL(pRBTree, pUncle) && RB_IS_BLACK(pUncle->pLeft))
            {
                RB_COLOR_BLACK(pUncle->pRight);
                RB_COLOR_RED(pUncle);
                LwRtlRBTreeRotateLeft(pRBTree, pUncle);
                pUncle = pParent->pLeft;
            }

            if (!RB_IS_NIL(pRBTree, pUncle))
            {
                RB_COPY_COLOR(pUncle, pParent);
            }
            RB_COLOR_BLACK(pParent);
            if (!RB_IS_NIL(pRBTree, pUncle))
            {
                RB_COLOR_BLACK(pUncle->pLeft);
                LwRtlRBTreeRotateRight(pRBTree, pParent);
            }
            pTreeNode = pRBTree->pRoot;
        }
    }

    RB_COLOR_BLACK(pTreeNode);
}
Exemplo n.º 13
0
NTSTATUS
LwRtlRBTreeAdd(
    PLWRTL_RB_TREE pRBTree,
    PVOID   pKey,
    PVOID   pData
    )
{
    NTSTATUS ntStatus = 0;
    PLWRTL_RB_TREE_NODE pTreeNode = NULL;
    PLWRTL_RB_TREE_NODE pUncle = NULL;
    PLWRTL_RB_TREE_NODE pParent = NULL;
    PLWRTL_RB_TREE_NODE pGrandParent = NULL;

    if (!pKey)
    {
        ntStatus = STATUS_INVALID_PARAMETER_2;
        BAIL_ON_NT_STATUS(ntStatus);
    }

    ntStatus = LW_RTL_ALLOCATE(
                    &pTreeNode,
                    LWRTL_RB_TREE_NODE,
                    sizeof(LWRTL_RB_TREE_NODE));
    BAIL_ON_NT_STATUS(ntStatus);

    pTreeNode->pKey = pKey;
    pTreeNode->pData = pData;
    pTreeNode->pRight = pRBTree->pSentinel;
    pTreeNode->pLeft = pRBTree->pSentinel;
    pTreeNode->pParent = NULL;

    LwRtlRBTreeInsert(pRBTree, pTreeNode);

    RB_COLOR_RED(pTreeNode);

    while ((pTreeNode != pRBTree->pRoot) && RB_IS_RED(pTreeNode->pParent))
    {
        pParent = RB_PARENT(pTreeNode);
        pGrandParent = RB_PARENT(pParent);

        if (pParent == pGrandParent->pLeft)
        {
            if (!RB_IS_NIL(pRBTree, pGrandParent))
            {
                pUncle = pGrandParent->pRight;

                if (RB_IS_RED(pUncle))
                {
                    RB_COLOR_BLACK(pParent);
                    RB_COLOR_BLACK(pUncle);
                    RB_COLOR_RED(pGrandParent);
                    pTreeNode = pGrandParent;
                    continue;
                }
            }

            if (pTreeNode == pParent->pRight)
            {
                pTreeNode = pParent;
                LwRtlRBTreeRotateLeft(pRBTree, pTreeNode);

                pParent = RB_PARENT(pTreeNode);
            }

            RB_COLOR_BLACK(pParent);
            if (!RB_IS_NIL(pRBTree, pGrandParent))
            {
                RB_COLOR_RED(pGrandParent);
                LwRtlRBTreeRotateRight(pRBTree, pGrandParent);
            }
        }
        else
        {
            if (!RB_IS_NIL(pRBTree, pGrandParent))
            {
                pUncle = pGrandParent->pLeft;

                if (RB_IS_RED(pUncle))
                {
                    RB_COLOR_BLACK(pParent);
                    RB_COLOR_BLACK(pUncle);
                    RB_COLOR_RED(pGrandParent);
                    pTreeNode = pGrandParent;
                    continue;
                }
            }

            if (pTreeNode == pParent->pLeft)
            {
                pTreeNode = pParent;
                LwRtlRBTreeRotateRight(pRBTree, pTreeNode);

                pParent = RB_PARENT(pTreeNode);
            }

            RB_COLOR_BLACK(pParent);
            if (!RB_IS_NIL(pRBTree, pGrandParent))
            {
                RB_COLOR_RED(pGrandParent);
                LwRtlRBTreeRotateLeft(pRBTree, pGrandParent);
            }
        }
    }

    RB_COLOR_BLACK(pRBTree->pRoot);

cleanup:

    return ntStatus;

error:

    if (pTreeNode) {
        LwRtlRBTreeFreeNode(pRBTree, pTreeNode);
    }

    goto cleanup;
}
Exemplo n.º 14
0
/*
 * rb_insert - insert node into Red-black tree
 */
static void rb_insert(void *node){
    void *parent, *child, *sib;

    RB_LEFT(node) = RB_RIGHT(node) = rb_null;
    parent = rb_root;
    child = RB_LEFT(rb_root);
    while(child != rb_null){
        parent = child;
        if(CUR_SIZE_MASKED(child) > CUR_SIZE_MASKED(node)){
            child = RB_LEFT(child);
        }else if(CUR_SIZE_MASKED(child) == CUR_SIZE_MASKED(node)){
            if(child > node){
                child = RB_LEFT(child);
            }else{
                child = RB_RIGHT(child);
            }
        }else{
            child = RB_RIGHT(child);
        }
    }
    RB_PARENT(node) = parent;
    if(parent == rb_root || CUR_SIZE_MASKED(parent) > CUR_SIZE_MASKED(node)){
        RB_LEFT(parent) = node;
    }else if(CUR_SIZE_MASKED(parent) == CUR_SIZE_MASKED(node)){
        if(parent > node){
            RB_LEFT(parent) = node;
        }else{
            RB_RIGHT(parent) = node;
        }
    }else{
        RB_RIGHT(parent) = node;
    }

    RB_RED(node) = 1;
    while(RB_RED(RB_PARENT(node))){
        if(RB_PARENT(node) == RB_LEFT(RB_PARENT(RB_PARENT(node)))){
            sib = RB_RIGHT(RB_PARENT(RB_PARENT(node)));
            if(RB_RED(sib)){
                RB_RED(RB_PARENT(node)) = 0;
                RB_RED(sib) = 0;
                RB_RED(RB_PARENT(RB_PARENT(node))) = 1;
                node = RB_PARENT(RB_PARENT(node));
            }else{
                if(node == RB_RIGHT(RB_PARENT(node))){
                    node = RB_PARENT(node);
                    rb_rotate_left(node);
                }
                RB_RED(RB_PARENT(node)) = 0;
                RB_RED(RB_PARENT(RB_PARENT(node))) = 1;
                rb_rotate_right(RB_PARENT(RB_PARENT(node)));
            }
        }else{
            sib = RB_LEFT(RB_PARENT(RB_PARENT(node)));
            if(RB_RED(sib)){
                RB_RED(RB_PARENT(node)) = 0;
                RB_RED(sib) = 0;
                RB_RED(RB_PARENT(RB_PARENT(node))) = 1;
                node = RB_PARENT(RB_PARENT(node));
            }else{
                if(node == RB_LEFT(RB_PARENT(node))){
                    node = RB_PARENT(node);
                    rb_rotate_right(node);
                }
                RB_RED(RB_PARENT(node)) = 0;
                RB_RED(RB_PARENT(RB_PARENT(node))) = 1;
                rb_rotate_left(RB_PARENT(RB_PARENT(node)));
            }
        }
    }
    RB_RED(RB_LEFT(rb_root)) = 0;
}
Exemplo n.º 15
0
/*
 * rb_delete - delete node from Red-black tree
 */
static void rb_delete(void *node){
    void *m, *c;
    m = RB_LEFT(node) == rb_null || RB_RIGHT(node) == rb_null ? node : rb_successor(node);
    c = RB_LEFT(m) == rb_null ? RB_RIGHT(m) : RB_LEFT(m);
    if((RB_PARENT(c) = RB_PARENT(m)) == rb_root){
        RB_LEFT(rb_root) = c;
    }else{
        if(RB_LEFT(RB_PARENT(m)) == m){
            RB_LEFT(RB_PARENT(m)) = c;
        }else{
            RB_RIGHT(RB_PARENT(m)) = c;
        }
    }
    if(m != node){
        if(!RB_RED(m)) rb_fix(c);
        RB_LEFT(m) = RB_LEFT(node);
        RB_RIGHT(m) = RB_RIGHT(node);
        RB_PARENT(m) = RB_PARENT(node);
        RB_RED(m) = RB_RED(node);
        RB_PARENT(RB_LEFT(node)) = RB_PARENT(RB_RIGHT(node)) = m;
        if(node == RB_LEFT(RB_PARENT(node))){
            RB_LEFT(RB_PARENT(node)) = m;
        }else{
            RB_RIGHT(RB_PARENT(node)) = m;
        }
    }else{
        if(!RB_RED(m)) rb_fix(c);
    }
}
Exemplo n.º 16
0
/*
 * rb_fix - restore properties of Red-black tree after deleting
 */
static void rb_fix(void *node){
    void *root, *sib;
    root = RB_LEFT(rb_root);
    while(!RB_RED(node) && node != root){
        if(node == RB_LEFT(RB_PARENT(node))){
            sib = RB_RIGHT(RB_PARENT(node));
            if(RB_RED(sib)){
                RB_RED(sib) = 0;
                RB_RED(RB_PARENT(node)) = 1;
                rb_rotate_left(RB_PARENT(node));
                sib = RB_RIGHT(RB_PARENT(node));
            }
            if(!RB_RED(RB_RIGHT(sib)) && !RB_RED(RB_LEFT(sib))){
                RB_RED(sib) = 1;
                node = RB_PARENT(node);
            }else{
                if(!RB_RED(RB_RIGHT(sib))){
                    RB_RED(RB_LEFT(sib)) = 0;
                    RB_RED(sib) = 1;
                    rb_rotate_right(sib);
                    sib = RB_RIGHT(RB_PARENT(node));
                }
                RB_RED(sib) = RB_RED(RB_PARENT(node));
                RB_RED(RB_PARENT(node)) = 0;
                RB_RED(RB_RIGHT(sib)) = 0;
                rb_rotate_left(RB_PARENT(node));
                node = root;
            }
        }else{
            sib = RB_LEFT(RB_PARENT(node));
            if(RB_RED(sib)){
                RB_RED(sib) = 0;
                RB_RED(RB_PARENT(node)) = 1;
                rb_rotate_right(RB_PARENT(node));
                sib = RB_LEFT(RB_PARENT(node));
            }
            if(!RB_RED(RB_RIGHT(sib)) && !RB_RED(RB_LEFT(sib))){
                RB_RED(sib) = 1;
                node = RB_PARENT(node);
            }else{
                if(!RB_RED(RB_LEFT(sib))){
                    RB_RED(RB_RIGHT(sib)) = 0;
                    RB_RED(sib) = 1;
                    rb_rotate_left(sib);
                    sib = RB_LEFT(RB_PARENT(node));
                }
                RB_RED(sib) = RB_RED(RB_PARENT(node));
                RB_RED(RB_PARENT(node)) = 0;
                RB_RED(RB_LEFT(sib)) = 0;
                rb_rotate_right(RB_PARENT(node));
                node = root;
            }
        }
        
    }
    RB_RED(node) = 0;
}
int
bu_rb_insert(struct bu_rb_tree *tree, void *data)
{
    int nm_orders;
    int order;
    int result = 0;
    struct bu_rb_node *node;
    struct bu_rb_package *package;
    struct bu_rb_list *rblp;

    BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");

    nm_orders = tree->rbt_nm_orders;

    /*
     * Enforce uniqueness
     *
     * NOTE: The approach is that for each order that requires
     * uniqueness, we look for a match.  This is not the most
     * efficient way to do things, since _rb_insert() is just going to
     * turn around and search the tree all over again.
     */
    for (order = 0; order < nm_orders; ++order) {
	if (RB_GET_UNIQUENESS(tree, order) &&
	    (bu_rb_search(tree, order, data) != NULL))
	{
	    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_UNIQ))
		bu_log("bu_rb_insert(<%p>, <%p>, TBD) will return %d\n",
		       (void*)tree, (void*)data, -(order + 1));
	    return -(order + 1);
	}
    }

    /*
     * Make a new package and add it to the list of all packages.
     */
    BU_ALLOC(package, struct bu_rb_package);
    package->rbp_node = (struct bu_rb_node **)
	bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
		  "red-black package nodes");

    BU_ALLOC(rblp, struct bu_rb_list);
    rblp->rbl_magic = BU_RB_LIST_MAGIC;
    rblp->rbl_package = package;

    BU_LIST_PUSH(&(tree->rbt_packages.l), rblp);
    package->rbp_list_pos = rblp;

    /*
     * Make a new node and add it to the list of all nodes.
     */
    node = (struct bu_rb_node *)
	bu_malloc(sizeof(struct bu_rb_node), "red-black node");
    node->rbn_parent = (struct bu_rb_node **)
	bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
		  "red-black parents");
    node->rbn_left = (struct bu_rb_node **)
	bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
		  "red-black left children");
    node->rbn_right = (struct bu_rb_node **)
	bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
		  "red-black right children");
    node->rbn_color = (char *)
	bu_malloc((size_t) lrint(ceil((double) (nm_orders / 8.0))),
		  "red-black colors");
    node->rbn_size = (int *)
	bu_malloc(nm_orders * sizeof(int),
		  "red-black subtree sizes");
    node->rbn_package = (struct bu_rb_package **)
	bu_malloc(nm_orders * sizeof(struct bu_rb_package *),
		  "red-black packages");

    BU_ALLOC(rblp, struct bu_rb_list);
    rblp->rbl_magic = BU_RB_LIST_MAGIC;
    rblp->rbl_node = node;

    BU_LIST_PUSH(&(tree->rbt_nodes.l), rblp);
    node->rbn_list_pos = rblp;

    /*
     * Fill in the package
     */
    package->rbp_magic = BU_RB_PKG_MAGIC;
    package->rbp_data = data;
    for (order = 0; order < nm_orders; ++order)
	(package->rbp_node)[order] = node;

    /*
     * Fill in the node
     */
    node->rbn_magic = BU_RB_NODE_MAGIC;
    node->rbn_tree = tree;
    for (order = 0; order < nm_orders; ++order)
	(node->rbn_package)[order] = package;
    node->rbn_pkg_refs = nm_orders;

    /*
     * If the tree was empty, install this node as the root and give
     * it a null parent and null children
     */
    if (RB_ROOT(tree, 0) == RB_NULL(tree)) {
	for (order = 0; order < nm_orders; ++order) {
	    RB_ROOT(tree, order) = node;
	    RB_PARENT(node, order) =
		RB_LEFT_CHILD(node, order) =
		RB_RIGHT_CHILD(node, order) = RB_NULL(tree);
	    RB_SET_COLOR(node, order, RB_BLK);
	    RB_SIZE(node, order) = 1;
	    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_OS))
		bu_log("bu_rb_insert(<%p>, <%p>, <%p>): size(%p, %d)=%d\n",
		       (void*)tree, (void*)data, (void*)node, (void*)node, order, RB_SIZE(node, order));
	}
    } else {
	/* Otherwise, insert the node into the tree */
	for (order = 0; order < nm_orders; ++order)
	    result += _rb_insert(tree, order, node);
	if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_UNIQ))
	    bu_log("bu_rb_insert(<%p>, <%p>, <%p>) will return %d\n",
		   (void*)tree, (void*)data, (void*)node, result);
    }

    ++(tree->rbt_nm_nodes);
    RB_CURRENT(tree) = node;
    return result;
}
Exemplo n.º 18
0
/* Note name changed. Guess why :) */
void rb_erase(struct rb_node *elm, struct rb_root *head) {
	struct rb_node *child, *parent, *old = elm;
	int color;
	if (RB_LEFT(elm) == NULL) {
		child = RB_RIGHT(elm);
	} else if (RB_RIGHT(elm) == NULL) {
		child = RB_LEFT(elm);
	} else {
		struct rb_node *left;
		elm = RB_RIGHT(elm);
		while ((left = RB_LEFT(elm))) {
			elm = left;
		}
		child = RB_RIGHT(elm);
		parent = RB_PARENT(elm);
		color = RB_COLOR(elm);
		if (child) {
			RB_PARENT(child) = parent;
		}
		if (parent) {
			if (RB_LEFT(parent) == elm) {
				RB_LEFT(parent) = child;
			} else {
				RB_RIGHT(parent) = child;
			}
			RB_AUGMENT(parent);
		} else {
			RB_HEAD(head) = child;
		}
		if (RB_PARENT(elm) == old) {
			parent = elm;
		}
		*(elm) = *(old);
		if (RB_PARENT(old)) {
			if (RB_LEFT(RB_PARENT(old)) == old) {
				RB_LEFT(RB_PARENT(old)) = elm;
			} else {
				RB_RIGHT(RB_PARENT(old)) = elm;
			}
			RB_AUGMENT(RB_PARENT(old));
		} else {
			RB_HEAD(head) = elm;
		}
		RB_PARENT(RB_LEFT(old)) = elm;
		if (RB_RIGHT(old)) {
			RB_PARENT(RB_RIGHT(old)) = elm;
		}
		if (parent) {
			left = parent;
			do {
				RB_AUGMENT(left);
			} while ((left = RB_PARENT(left)));
		}
		goto color;
	}
	parent = RB_PARENT(elm);
	color = RB_COLOR(elm);
	if (child) {
		RB_PARENT(child) = parent;
	}
	if (parent) {
		if (RB_LEFT(parent) == elm) {
			RB_LEFT(parent) = child;
		} else {
			RB_RIGHT(parent) = child;
		}
		RB_AUGMENT(parent);
	} else {
		RB_HEAD(head) = child;
	}
color:
	if (color == RB_BLACK) {
		rb_remove_color(head, parent, child);
	}
}
Exemplo n.º 19
0
static void rb_remove_color(struct rb_root *head, struct rb_node *parent,
			    struct rb_node *elm) {
	struct rb_node *tmp;
	while ((elm == NULL || RB_COLOR(elm) == RB_BLACK) &&
	    elm != RB_HEAD(head)) {
		if (RB_LEFT(parent) == elm) {
			tmp = RB_RIGHT(parent);
			if (RB_COLOR(tmp) == RB_RED) {
				RB_SET_BLACKRED(tmp, parent);
				RB_ROTATE_LEFT(head, parent, tmp);
				tmp = RB_RIGHT(parent);
			}
			if ((RB_LEFT(tmp) == NULL ||
			    RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) &&
			    (RB_RIGHT(tmp) == NULL ||
			    RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) {
				RB_COLOR(tmp) = RB_RED;
				elm = parent;
				parent = RB_PARENT(elm);
			} else {
				if (RB_RIGHT(tmp) == NULL ||
				    RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK) {
					struct rb_node *oleft;
					if ((oleft = RB_LEFT(tmp)))
						RB_COLOR(oleft) = RB_BLACK;
					RB_COLOR(tmp) = RB_RED;
					RB_ROTATE_RIGHT(head, tmp, oleft);
					tmp = RB_RIGHT(parent);
				}
				RB_COLOR(tmp) = RB_COLOR(parent);
				RB_COLOR(parent) = RB_BLACK;
				if (RB_RIGHT(tmp))
					RB_COLOR(RB_RIGHT(tmp)) = RB_BLACK;
				RB_ROTATE_LEFT(head, parent, tmp);
				elm = RB_HEAD(head);
				break;
			}
		} else {
			tmp = RB_LEFT(parent);
			if (RB_COLOR(tmp) == RB_RED) {
				RB_SET_BLACKRED(tmp, parent);
				RB_ROTATE_RIGHT(head, parent, tmp);
				tmp = RB_LEFT(parent);
			}
			if ((RB_LEFT(tmp) == NULL ||
			    RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) &&
			    (RB_RIGHT(tmp) == NULL ||
			    RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) {
				RB_COLOR(tmp) = RB_RED;
				elm = parent;
				parent = RB_PARENT(elm);
			} else {
				if (RB_LEFT(tmp) == NULL ||
				    RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) {
					struct rb_node *oright;
					if ((oright = RB_RIGHT(tmp)))
						RB_COLOR(oright) = RB_BLACK;
					RB_COLOR(tmp) = RB_RED;
					RB_ROTATE_LEFT(head, tmp, oright);
					tmp = RB_LEFT(parent);
				}
				RB_COLOR(tmp) = RB_COLOR(parent);
				RB_COLOR(parent) = RB_BLACK;
				if (RB_LEFT(tmp))
					RB_COLOR(RB_LEFT(tmp)) = RB_BLACK;
				RB_ROTATE_RIGHT(head, parent, tmp);
				elm = RB_HEAD(head);
				break;
			}
		}
	}
	if (elm)
		RB_COLOR(elm) = RB_BLACK;
}
/**
 * Insert a node into one linear order of a red-black tree
 *
 * This function has three parameters: the tree and linear order into
 * which to insert the new node and the new node itself.  If the node
 * is equal (modulo the linear order) to a node already in the tree,
 * _rb_insert() returns 1.  Otherwise, it returns 0.
 */
HIDDEN int
_rb_insert(struct bu_rb_tree *tree, int order, struct bu_rb_node *new_node)
{
    struct bu_rb_node *node;
    struct bu_rb_node *parent;
    struct bu_rb_node *grand_parent;
    struct bu_rb_node *y;
    int (*compare)(const void *, const void *);
    int comparison = 0xdeadbeef;
    int direction;
    int result = 0;


    BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
    RB_CKORDER(tree, order);
    BU_CKMAG(new_node, BU_RB_NODE_MAGIC, "red-black node");

    /*
     * Initialize the new node
     */
    RB_PARENT(new_node, order) =
	RB_LEFT_CHILD(new_node, order) =
	RB_RIGHT_CHILD(new_node, order) = RB_NULL(tree);
    RB_SIZE(new_node, order) = 1;
    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_OS))
	bu_log("_rb_insert(%p): size(%p, %d)=%d\n",
	       (void*)new_node, (void*)new_node, order, RB_SIZE(new_node, order));

    /*
     * Perform vanilla-flavored binary-tree insertion
     */
    parent = RB_NULL(tree);
    node = RB_ROOT(tree, order);
    compare = RB_COMPARE_FUNC(tree, order);
    while (node != RB_NULL(tree)) {
	parent = node;
	++RB_SIZE(parent, order);
	if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_OS))
	    bu_log("_rb_insert(%p): size(%p, %d)=%d\n",
		   (void*)new_node, (void*)parent, order, RB_SIZE(parent, order));
	comparison = compare(RB_DATA(new_node, order),
			     RB_DATA(node, order));
	if (comparison < 0) {
	    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_INSERT))
		bu_log("_rb_insert(%p): <_%d <%p>, going left\n",
		       (void*)new_node, order, (void*)node);
	    node = RB_LEFT_CHILD(node, order);
	} else {
	    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_INSERT))
		bu_log("_rb_insert(%p): >=_%d <%p>, going right\n",
		       (void*)new_node, order, (void*)node);
	    node = RB_RIGHT_CHILD(node, order);
	    if (comparison == 0)
		result = 1;
	}
    }
    RB_PARENT(new_node, order) = parent;
    if (parent == RB_NULL(tree))
	RB_ROOT(tree, order) = new_node;
    else if ((compare(RB_DATA(new_node, order),
		      RB_DATA(parent, order))) < 0)
	RB_LEFT_CHILD(parent, order) = new_node;
    else
	RB_RIGHT_CHILD(parent, order) = new_node;

    /*
     * Reestablish the red-black properties, as necessary
     */
    RB_SET_COLOR(new_node, order, RB_RED);
    node = new_node;
    parent = RB_PARENT(node, order);
    grand_parent = RB_PARENT(parent, order);
    while ((node != RB_ROOT(tree, order))
	   && (RB_GET_COLOR(parent, order) == RB_RED))
    {
	if (parent == RB_LEFT_CHILD(grand_parent, order))
	    direction = RB_LEFT;
	else
	    direction = RB_RIGHT;

	y = RB_OTHER_CHILD(grand_parent, order, direction);
	if (RB_GET_COLOR(y, order) == RB_RED) {
	    RB_SET_COLOR(parent, order, RB_BLK);
	    RB_SET_COLOR(y, order, RB_BLK);
	    RB_SET_COLOR(grand_parent, order, RB_RED);
	    node = grand_parent;
	    parent = RB_PARENT(node, order);
	    grand_parent = RB_PARENT(parent, order);
	} else {
	    if (node == RB_OTHER_CHILD(parent, order, direction)) {
		node = parent;
		RB_ROTATE(node, order, direction);
		parent = RB_PARENT(node, order);
		grand_parent = RB_PARENT(parent, order);
	    }
	    RB_SET_COLOR(parent, order, RB_BLK);
	    RB_SET_COLOR(grand_parent, order, RB_RED);
	    RB_OTHER_ROTATE(grand_parent, order, direction);
	}
    }
    RB_SET_COLOR(RB_ROOT(tree, order), order, RB_BLK);

    if (UNLIKELY(tree->rbt_debug & BU_RB_DEBUG_INSERT))
	bu_log("_rb_insert(%p): comparison = %d, returning %d\n",
	       (void*)new_node, comparison, result);

    return result;
}