diff --git a/sandbox/btree/btree.c b/sandbox/btree/btree.c index 53daab3..8fcd858 100644 --- a/sandbox/btree/btree.c +++ b/sandbox/btree/btree.c @@ -1,15 +1,135 @@ -#include "include/socks/btree.h" -#include +#include +#include +#include -static void insert_fixup(btree_t *tree, btree_node_t *node) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define IS_LEFT_CHILD(p, c) ((p) && (c) && ((p)->b_left == (c))) +#define IS_RIGHT_CHILD(p, c) ((p) && (c) && ((p)->b_right == (c))) + +static void rotate_left(btree_t *tree, btree_node_t *x) { + btree_node_t *y = x->b_right; + btree_node_t *p = x->b_parent; + if (y->b_left) { + y->b_left->b_parent = x; + } + + x->b_right = y->b_left; + + if (!p) { + tree->b_root = y; + } else if (x == p->b_left) { + p->b_left = y; + } else { + p->b_right = y; + } + + x->b_parent = y; + y->b_left = x; + y->b_parent = p; + + x->b_bfactor = x->b_bfactor - 1 - MAX(y->b_bfactor, 0); + + p = y; + + while (p) { + p->b_bfactor = p->b_bfactor - 1 + MIN(y->b_bfactor, 0); + x = p; + p = p->b_parent; + } +} + +static void rotate_right(btree_t *tree, btree_node_t *y) +{ + btree_node_t *x = y->b_left; + btree_node_t *p = y->b_parent; + + if (x->b_right) { + x->b_right->b_parent = y; + } + + y->b_left = x->b_right; + + if (!p) { + tree->b_root = x; + } else if (x == p->b_left) { + p->b_left = x; + } else { + p->b_right = x; + } + + y->b_parent = x; + x->b_right = y; + x->b_parent = p; + + y->b_bfactor = y->b_bfactor + 1 - MIN(x->b_bfactor, 0); + + p = x; + while (p) { + p->b_bfactor = x->b_bfactor + 1 + MAX(y->b_bfactor, 0); + y = p; + } +} + +static void rotate_double_left(btree_t *tree, btree_node_t *z) +{ + btree_node_t *x = z->b_right; + btree_node_t *y = x->b_left; + + rotate_right(tree, x); + rotate_left(tree, z); +} + +static void rotate_double_right(btree_t *tree, btree_node_t *z) +{ + btree_node_t *x = z->b_left; + btree_node_t *y = x->b_right; + + rotate_left(tree, x); + rotate_right(tree, z); +} + +static void insert_fixup(btree_t *tree, btree_node_t *w) +{ + btree_node_t *z = NULL, *y = NULL, *x = NULL; + + z = w; + while (z) { + if (z->b_bfactor >= -1 && z->b_bfactor <= 1) { + goto next_ancestor; + } + + + if (IS_LEFT_CHILD(z, y)) { + if (IS_LEFT_CHILD(y, x)) { + rotate_right(tree, z); + } else { + rotate_double_right(tree, z); + } + } else { + if (IS_LEFT_CHILD(y, x)) { + rotate_double_left(tree, z); + } else { + rotate_left(tree, z); + } + } + + +next_ancestor: + x = y; + y = z; + z = z->b_parent; + } } void btree_insert(btree_t *tree, btree_node_t *node) { if (!tree->b_root) { tree->b_root = node; + node->b_parent = NULL; return; } @@ -17,21 +137,31 @@ void btree_insert(btree_t *tree, btree_node_t *node) while (1) { btree_node_t **nextp = NULL; + int bfactor_diff = 0; if (node->b_key >= cur->b_key) { nextp = &cur->b_right; + bfactor_diff = 1; } else { nextp = &cur->b_left; + bfactor_diff = -1; } + cur->b_bfactor = cur->b_bfactor + bfactor_diff; + if (*nextp) { cur = *nextp; } else { + node->b_parent = cur; *nextp = node; break; } } + node->b_bfactor = 0; insert_fixup(tree, node); } -void btree_delete(btree_t *tree, btree_node_t *node) {} +void btree_delete(btree_t *tree, btree_node_t *node) +{ + +} diff --git a/sandbox/btree/include/socks/btree.h b/sandbox/btree/include/socks/btree.h index 7768215..c64eea7 100644 --- a/sandbox/btree/include/socks/btree.h +++ b/sandbox/btree/include/socks/btree.h @@ -6,7 +6,7 @@ typedef uint64_t btree_key_t; typedef struct btree_node { - struct btree_node *b_left, *b_right; + struct btree_node *b_parent, *b_left, *b_right; signed char b_bfactor; btree_key_t b_key; } btree_node_t;