From e5130a638377751197c5f574533efe2325e23591 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 Jan 2023 20:57:08 +0100 Subject: [PATCH] feat(tree): bit flag so children know which child they are --- src/tree/vieter_tree.c | 2 +- src/tree/vieter_tree_balancing.c | 134 +++++++++++++++++-------------- src/tree/vieter_tree_node.c | 24 +++--- src/tree/vieter_tree_node.h | 3 +- 4 files changed, 89 insertions(+), 74 deletions(-) diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index 92f8831..b066af1 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -16,7 +16,7 @@ vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, tree->root = vieter_tree_node_init(); tree->root->key = key; tree->root->data = data; - vieter_tree_node_set(tree->root, vieter_tree_node_black); + vieter_tree_node_set(tree->root, vieter_tree_node_black, true); tree->size = 1; return vieter_tree_ok; diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index c04825d..6a58179 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -1,4 +1,5 @@ #include "vieter_tree_balancing.h" +#include bool vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, @@ -38,85 +39,96 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { uint64_t key_root = root->key; void *data_root = root->data; - if (node->key < parent->key && parent->key < grand_parent->key) { - root->key = parent->key; - root->data = parent->data; - - parent->key = key_root; - parent->data = data_root; - - left = node; - right = parent; - - children[0] = node->children[0]; - children[1] = node->children[1]; - children[2] = parent->children[1]; - children[3] = grand_parent->children[1]; - } else if (node->key < parent->key && parent->key > grand_parent->key) { - root->key = node->key; - root->data = node->data; - - node->key = key_root; - node->data = data_root; - - left = node; - right = parent; - - children[0] = grand_parent->children[0]; - children[1] = node->children[0]; - children[2] = node->children[1]; - children[3] = parent->children[1]; - } else if (node->key > parent->key && parent->key < grand_parent->key) { - root->key = node->key; - root->data = node->data; - - node->key = key_root; - node->data = data_root; - + if (vieter_tree_node_get(node, vieter_tree_node_right)) { left = parent; right = node; - children[0] = parent->children[0]; - children[1] = node->children[0]; - children[2] = node->children[1]; - children[3] = grand_parent->children[1]; + if (vieter_tree_node_get(parent, vieter_tree_node_right)) { + root->key = parent->key; + root->data = parent->data; + + parent->key = key_root; + parent->data = data_root; + + children[0] = grand_parent->children[0]; + children[1] = parent->children[0]; + children[2] = node->children[0]; + children[3] = node->children[1]; + } else { + root->key = node->key; + root->data = node->data; + + node->key = key_root; + node->data = data_root; + + children[0] = parent->children[0]; + children[1] = node->children[0]; + children[2] = node->children[1]; + children[3] = grand_parent->children[1]; + } } else { - root->key = parent->key; - root->data = parent->data; + left = node; + right = parent; - parent->key = key_root; - parent->data = data_root; + if (vieter_tree_node_get(parent, vieter_tree_node_right)) { + root->key = node->key; + root->data = node->data; - left = parent; - right = node; + node->key = key_root; + node->data = data_root; - children[0] = grand_parent->children[0]; - children[1] = parent->children[0]; - children[2] = node->children[0]; - children[3] = node->children[1]; + children[0] = grand_parent->children[0]; + children[1] = node->children[0]; + children[2] = node->children[1]; + children[3] = parent->children[1]; + } else { + root->key = parent->key; + root->data = parent->data; + + parent->key = key_root; + parent->data = data_root; + + children[0] = node->children[0]; + children[1] = node->children[1]; + children[2] = parent->children[1]; + children[3] = grand_parent->children[1]; + } } - vieter_tree_node_set(left, vieter_tree_node_black); - vieter_tree_node_set(right, vieter_tree_node_black); - vieter_tree_node_unset(root, vieter_tree_node_black); + vieter_tree_node_set( + root, vieter_tree_node_right, + vieter_tree_node_get(grand_parent, vieter_tree_node_right)); - left->children[0] = children[0]; - left->children[1] = children[1]; + vieter_tree_node_set(left, vieter_tree_node_black, true); + vieter_tree_node_set(left, vieter_tree_node_right, false); + vieter_tree_node_set(right, vieter_tree_node_black, true); + vieter_tree_node_set(left, vieter_tree_node_right, true); - if (children[0] != NULL) + vieter_tree_node_set(root, vieter_tree_node_black, false); + + memcpy(&left->children, children, 2 * sizeof(vieter_tree_node *)); + + if (children[0] != NULL) { children[0]->parent = left; + vieter_tree_node_set(children[0], vieter_tree_node_right, false); + } - if (children[1] != NULL) + if (children[1] != NULL) { children[1]->parent = left; + vieter_tree_node_set(children[0], vieter_tree_node_right, true); + } - right->children[0] = children[2]; - right->children[1] = children[3]; + memcpy(&right->children, children + 2, 2 * sizeof(vieter_tree_node *)); - if (children[2] != NULL) + if (children[2] != NULL) { children[2]->parent = right; + vieter_tree_node_set(children[2], vieter_tree_node_right, false); + } - if (children[3] != NULL) + if (children[3] != NULL) { children[3]->parent = right; + vieter_tree_node_set(children[2], vieter_tree_node_right, true); + } root->children[0] = left; root->children[1] = right; @@ -135,7 +147,7 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { // The root must always be black if (node->parent == NULL) { - vieter_tree_node_set(node, vieter_tree_node_black); + vieter_tree_node_set(node, vieter_tree_node_black, true); } } diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index ca506b9..853281a 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -1,6 +1,8 @@ #include "vieter_tree_node.h" #include "vieter_tree_balancing.h" +#include + vieter_tree_node *vieter_tree_node_init() { return calloc(1, sizeof(vieter_tree_node)); } @@ -13,10 +15,12 @@ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, return; } - parent->children[key > parent->key] = child; + bool side = key > parent->key; + parent->children[side] = child; if (child != NULL) { child->parent = parent; + vieter_tree_node_set(child, vieter_tree_node_right, side); } } @@ -24,8 +28,8 @@ void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement) { to_replace->key = replacement->key; to_replace->data = replacement->data; - to_replace->children[0] = replacement->children[0]; - to_replace->children[1] = replacement->children[1]; + memcpy(to_replace->children, replacement->children, + 2 * sizeof(vieter_tree_node *)); if (to_replace->children[0] != NULL) to_replace->children[0]->parent = to_replace; @@ -140,13 +144,13 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, return vieter_tree_ok; } -void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag) { - node->flags |= flag; -} - -void vieter_tree_node_unset(vieter_tree_node *node, - vieter_tree_node_flag flag) { - node->flags &= ~flag; +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, + bool set) { + if (set) { + node->flags |= flag; + } else { + node->flags &= ~flag; + } } bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag) { diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 21bbb81..4012d1d 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -37,8 +37,7 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, ui void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement); -void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag); -void vieter_tree_node_unset(vieter_tree_node *node, vieter_tree_node_flag flag); +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, bool value); bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag); void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key,