diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-10-29 23:29:23 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-29 23:31:56 -0700 |
commit | 3e364fe27482c09b33c85b401f601ba7ba5c48bb (patch) | |
tree | 0d1f05cb5b4329812d4888465e95fa1d1963f261 /rbtree.c | |
parent | 034b009e51fd564f912874f2a59549edc358cbca (diff) | |
download | nasm-3e364fe27482c09b33c85b401f601ba7ba5c48bb.tar.gz nasm-3e364fe27482c09b33c85b401f601ba7ba5c48bb.tar.bz2 nasm-3e364fe27482c09b33c85b401f601ba7ba5c48bb.zip |
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 <hpa@zytor.com>
Diffstat (limited to 'rbtree.c')
-rw-r--r-- | rbtree.c | 100 |
1 files changed, 100 insertions, 0 deletions
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); + } +} |