From 3e364fe27482c09b33c85b401f601ba7ba5c48bb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 29 Oct 2008 23:29:23 -0700 Subject: Left-leaning red-black tree data structure Implement library functions for "left-leaning red-black trees" with uint64_t keys. This is meant for looking up symbols by address in the backends that need to do so, e.g. ELF. A good question is if there is a better way to do this, that recovers the original symbol, but that's a future issue. Signed-off-by: H. Peter Anvin --- rbtree.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 rbtree.c (limited to 'rbtree.c') diff --git a/rbtree.c b/rbtree.c new file mode 100644 index 0000000..adf2b8b --- /dev/null +++ b/rbtree.c @@ -0,0 +1,100 @@ +/* + * rbtree.c + * + * Simple implementation of a left-leaning red-black tree with 64-bit + * integer keys. The search operation will return the highest node <= + * the key; only search, insert, and full-tree deletion is supported, + * but additional standard llrbtree operations can be coded up at will. + * + * See http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf for + * information about left-leaning red-black trees. + */ + +#include "rbtree.h" +#include "nasmlib.h" + +const struct rbtree *rb_search(const struct rbtree *tree, uint64_t key) +{ + const struct rbtree *best = NULL; + + while (tree) { + if (tree->key == key) + return tree; + else if (tree->key > key) + tree = tree->left; + else { + best = tree; + tree = tree->right; + } + } + return best; +} + +static bool is_red(struct rbtree *h) +{ + return h && h->red; +} + +static struct rbtree *rotate_left(struct rbtree *h) +{ + struct rbtree *x = h->right; + h->right = x->left; + x->left = h; + x->red = x->left->red; + x->left->red = true; + return x; +} + +static struct rbtree *rotate_right(struct rbtree *h) +{ + struct rbtree *x = h->left; + h->left = x->right; + x->right = h; + x->red = x->right->red; + x->right->red = true; + return x; +} + +static void color_flip(struct rbtree *h) +{ + h->red = !h->red; + h->left->red = !h->left->red; + h->right->red = !h->right->red; +} + +struct rbtree *rb_insert(struct rbtree *tree, uint64_t key, void *data) +{ + if (!tree) { + struct rbtree *node = nasm_malloc(sizeof *node); + + node->key = key; + node->data = data; + node->red = true; + return node; + } + + if (is_red(tree->left) && is_red(tree->right)) + color_flip(tree); + + if (key < tree->key) + tree->left = rb_insert(tree->left, key, data); + else + tree->right = rb_insert(tree->right, key, data); + + if (is_red(tree->right)) + tree = rotate_left(tree); + + if (is_red(tree->left) && is_red(tree->left->left)) + tree = rotate_right(tree); + + return tree; +} + +void rb_free(struct rbtree *tree) +{ + if (tree) { + rb_free(tree->left); + rb_free(tree->right); + nasm_free(tree); + } +} -- cgit v1.2.3