コード例 #1
0
ファイル: c-rbtree.c プロジェクト: c-util/c-rbtree
/**
 * c_rbnode_next_postorder() - return next node in post-order
 * @n:          current node, or NULL
 *
 * This returns the next node to @n, based on a left-to-right post-order
 * traversal. If @n is NULL, the root node, or unlinked, this returns NULL.
 *
 * This implements a left-to-right post-order traversal: First visit the left
 * child of a node, then the right, and lastly the node itself. Children are
 * traversed recursively.
 *
 * This function can be used to implement a left-to-right post-order traversal:
 *
 *     for (n = c_rbtree_first_postorder(t); n; n = c_rbnode_next_postorder(n))
 *             visit(n);
 *
 * Worst case runtime (n: number of elements in tree): O(log(n))
 *
 * Return: Pointer to next node, or NULL.
 */
_c_public_ CRBNode *c_rbnode_next_postorder(CRBNode *n) {
        CRBNode *p;

        if (!c_rbnode_is_linked(n))
                return NULL;

        p = c_rbnode_parent(n);
        if (p && n == p->left && p->right)
                return c_rbnode_leftdeepest(p->right);

        return p;
}
コード例 #2
0
ファイル: c-rbtree.c プロジェクト: c-util/c-rbtree
/**
 * c_rbnode_prev() - return previous node
 * @n:          current node, or NULL
 *
 * An RB-Tree always defines a linear order of its elements. This function
 * returns the logically previous node to @n. If @n is NULL, the first node or
 * unlinked, this returns NULL.
 *
 * Worst case runtime (n: number of elements in tree): O(log(n))
 *
 * Return: Pointer to previous node, or NULL.
 */
_c_public_ CRBNode *c_rbnode_prev(CRBNode *n) {
        CRBNode *p;

        if (!c_rbnode_is_linked(n))
                return NULL;
        if (n->left)
                return c_rbnode_rightmost(n->left);

        while ((p = c_rbnode_parent(n)) && n == p->left)
                n = p;

        return p;
}
コード例 #3
0
ファイル: c-rbtree.c プロジェクト: c-util/c-rbtree
/**
 * c_rbnode_prev_postorder() - return previous node in post-order
 * @n:          current node, or NULL
 *
 * This returns the previous node to @n, based on a left-to-right post-order
 * traversal. That is, it is the inverse operation to c_rbnode_next_postorder().
 * If @n is NULL, the left-deepest node, or unlinked, this returns NULL.
 *
 * This function returns the logical previous node in a directed post-order
 * traversal. That is, it effectively does a pre-order traversal (since a
 * reverse post-order traversal is a pre-order traversal). This function does
 * NOT do a right-to-left post-order traversal! In other words, the following
 * invariant is guaranteed, if c_rbnode_next_postorder(n) is non-NULL:
 *
 *     n == c_rbnode_prev_postorder(c_rbnode_next_postorder(n))
 *
 * This function can be used to implement a right-to-left pre-order traversal,
 * using the fact that a reverse post-order traversal is also a valid pre-order
 * traversal:
 *
 *     for (n = c_rbtree_last_postorder(t); n; n = c_rbnode_prev_postorder(n))
 *             visit(n);
 *
 * This would effectively perform a right-to-left pre-order traversal: first
 * visit a parent, then its right child, then its left child. Both children are
 * traversed recursively.
 *
 * Worst case runtime (n: number of elements in tree): O(log(n))
 *
 * Return: Pointer to previous node in post-order, or NULL.
 */
_c_public_ CRBNode *c_rbnode_prev_postorder(CRBNode *n) {
        CRBNode *p;

        if (!c_rbnode_is_linked(n))
                return NULL;
        if (n->right)
                return n->right;
        if (n->left)
                return n->left;

        while ((p = c_rbnode_parent(n))) {
                if (p->left && n != p->left)
                        return p->left;
                n = p;
        }

        return NULL;
}
コード例 #4
0
ファイル: c-rbtree.c プロジェクト: c-util/c-rbtree
 * This function does *NOT* perform a full swap, nor does it touch any 'parent'
 * pointer.
 *
 * The sole purpose of this function is to shortcut left/right conditionals
 * like this:
 *
 *     if (old == old->parent->left)
 *             old->parent->left = new;
 *     else
 *             old->parent->right = new;
 *
 * That's it! If @old is the root node, this will do nothing. The caller must
 * employ c_rbnode_pop_root() and c_rbnode_push_root().
 */
static inline void c_rbnode_swap_child(CRBNode *old, CRBNode *new) {
        CRBNode *p = c_rbnode_parent(old);

        if (p) {
                if (p->left == old)
                        c_rbtree_store(&p->left, new);
                else
                        c_rbtree_store(&p->right, new);
        }
}

/**
 * c_rbtree_move() - move tree
 * @to:         destination tree
 * @from:       source tree
 *
 * This imports the entire tree from @from into @to. @to must be empty! @from
コード例 #5
0
ファイル: test-rbtree.c プロジェクト: CyberShadow/systemd
static size_t validate(CRBTree *t) {
        unsigned int i_black, n_black;
        CRBNode *n, *p, *o;
        size_t count = 0;

        assert(t);
        assert(!t->root || c_rbnode_is_black(t->root));

        /* traverse to left-most child, count black nodes */
        i_black = 0;
        n = t->root;
        while (n && n->left) {
                if (c_rbnode_is_black(n))
                        ++i_black;
                n = n->left;
        }
        n_black = i_black;

        /*
         * Traverse tree and verify correctness:
         *  1) A node is either red or black
         *  2) The root is black
         *  3) All leaves are black
         *  4) Every red node must have two black child nodes
         *  5) Every path to a leaf contains the same number of black nodes
         *
         * Note that NULL nodes are considered black, which is why we don't
         * check for 3).
         */
        o = NULL;
        while (n) {
                ++count;

                /* verify natural order */
                assert(n > o);
                o = n;

                /* verify consistency */
                assert(!n->right || c_rbnode_parent(n->right) == n);
                assert(!n->left || c_rbnode_parent(n->left) == n);

                /* verify 2) */
                if (!c_rbnode_parent(n))
                        assert(c_rbnode_is_black(n));

                if (c_rbnode_is_red(n)) {
                        /* verify 4) */
                        assert(!n->left || c_rbnode_is_black(n->left));
                        assert(!n->right || c_rbnode_is_black(n->right));
                } else {
                        /* verify 1) */
                        assert(c_rbnode_is_black(n));
                }

                /* verify 5) */
                if (!n->left && !n->right)
                        assert(i_black == n_black);

                /* get next node */
                if (n->right) {
                        n = n->right;
                        if (c_rbnode_is_black(n))
                                ++i_black;

                        while (n->left) {
                                n = n->left;
                                if (c_rbnode_is_black(n))
                                        ++i_black;
                        }
                } else {
                        while ((p = c_rbnode_parent(n)) && n == p->right) {
                                n = p;
                                if (c_rbnode_is_black(p->right))
                                        --i_black;
                        }

                        n = p;
                        if (p && c_rbnode_is_black(p->left))
                                --i_black;
                }
        }

        return count;
}