#include #include #include #include "tree.h" static node_t *create_node(unsigned int index, char *val) { node_t *node = malloc( sizeof(node_t) ); memset(node, 0, sizeof(node_t)); node->value = val; node->index = index; } /* Comments are based of dir = CHILD_LEFT */ void node_rotate(tree_t *tree, node_t *x, int dir) { /* Node below which we should rotate with */ node_t *y = x->children[!dir]; /* Move y's left to x's right */ x->children[!dir] = y->children[dir]; /* Update parent */ if ( y->children[dir] ) { y->children[dir]->p = x; } /* Switch around x and y */ y->p = x->p; /* Check if y is new root if not update x's parent */ if ( !y->p ) { tree->root = y; } else if ( x == x->p->children[CHILD_LEFT]) { x->p->children[CHILD_LEFT] = y; } else { x->p->children[CHILD_RIGHT] = y; } /* Update y's ref */ y->children[dir] = x; x->p = y; } static void insert_fixup(tree_t *tree, node_t *z) { while ( z->p && z->p->black == false ) { /* Set the right direction */ int dir = (z->p == z->p->p->children[CHILD_LEFT]) ? CHILD_RIGHT : CHILD_LEFT; /* Get uncle */ node_t *y = z->p->p->children[dir]; if ( y && !y->black ) { /* Case 1 */ z->p->black = true; y->black = true; z->p->p->black = false; z = z->p->p; } else if ( z == z->p->children[dir] ) { /* Case 2 */ z = z->p; node_rotate(tree, z, !dir); } else { /* Case 3 */ z->p->black = true; z->p->p->black = false; node_rotate(tree, z->p->p, dir); } } tree->root->black = true; } static node_t *insert_recur(node_t *node, unsigned int index, char *val) { int dir = node->index < index ? CHILD_RIGHT : CHILD_LEFT; if ( node->children[dir] ) { return insert_recur(node->children[dir], index, val); } /* Found stop */ node_t *new = create_node(index, val); new->p = node; node->children[dir] = new; return new; } node_t *tree_insert_pleb(tree_t *tree, unsigned int index, char *val) { if ( !tree->root ) { tree->root = create_node(index, val); return tree->root; } return insert_recur(tree->root, index, val); } node_t *tree_insert(tree_t *tree, unsigned int index, char *val) { if ( !tree->root ) { tree->root = create_node(index, val); tree->root->black = true; return tree->root; } node_t *new = insert_recur(tree->root, index, val); insert_fixup(tree, new); return new; } char *tree_search(tree_t *tree, unsigned int index) { node_t *z = tree->root; while ( z->index != index ) { z = z->children[z->index < index ? CHILD_RIGHT : CHILD_LEFT]; if ( !z ) { return NULL; } } return z->value; } static inline void print_indent(int num) { for ( int i = 0; i < num; i++ ) { printf(" "); } } static inline void print_text(node_t *node, bool bold) { if ( bold ) { printf("\033[1m%d\033[22m\n", node->index); } else { printf("%d\n", node->index); } } static void print_recur(node_t *node, int ident) { if ( !node ) { return; } print_recur(node->children[CHILD_RIGHT], ident+1); print_indent(ident); print_text(node, node->black); print_recur(node->children[CHILD_LEFT], ident+1); } void tree_print(tree_t *tree) { print_recur(tree->root, 0); }