From 98bea5b32aa14b5f79120798ef4f6753dbf0138c Mon Sep 17 00:00:00 2001 From: Phireh Date: Mon, 17 Feb 2025 21:03:09 +0100 Subject: [PATCH] Initial implementation of Btree --- Makefile | 2 +- list.h | 2 +- tree.h | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 122 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 3ff2d8e..d7edac6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ IHCT_CFLAGS=-Wall -Wextra -Wpedantic -Wfatal-errors -std=gnu99 -fPIC -shared TEST_CFLAGS=-Wall -Wextra -Wpedantic -Wfatal-errors -DIHCT_SHORT -L./ -Wl,-rpath ./ -tests: tests.c list.h libihct.so +tests: tests.c list.h tree.h libihct.so gcc $(TEST_CFLAGS) tests.c -lihct -o tests libihct.so: ihct/vector.c ihct/ihct.c diff --git a/list.h b/list.h index 677bebc..b0b9ed6 100644 --- a/list.h +++ b/list.h @@ -139,7 +139,7 @@ typedef struct dnode_ { void *vptr; }; dnode_ptr next; - dnode_ptr prev; + dnode_ptr prev; } dnode_t; void dlist_append(dnode_t *start, dnode_t *tail) diff --git a/tree.h b/tree.h index ae72a08..192e0f7 100644 --- a/tree.h +++ b/tree.h @@ -1,5 +1,7 @@ #ifndef TREE_H #define TREE_H +#include +#include typedef struct tnode_ tnode_t; typedef struct tnode_* tnode_ptr; typedef enum { INT, UINT, CHAR, FLOAT, DOUBLE, CHAR_PTR, VOID_PTR } tnode_value_t; @@ -12,21 +14,131 @@ typedef struct tnode_ { char vc; float vf; double vd; - char* vcp; + char *vcp; void *vptr; }; tnode_ptr parent; - tnode_ptr left_leaf; - tnode_ptr right_leaf; + tnode_ptr left_child; + tnode_ptr right_child; } tnode_t; - -tnode_t* tree_root(tnode_t* leaf) +int compare(int type, void *left, void *right) { - tnode_t* current = leaf; + switch (type) + { + case INT: + return *((int*)left) - *((int*)right); + case UINT: + return *((unsigned int*)left) - *((unsigned int*)right); + case FLOAT: + return *((float*)left) - *((float*)right); + case DOUBLE: + return *((float*)left) - *((float*)right); + case CHAR_PTR: + return strcmp((char*)left, (char*)right); + default: + return 0; + } +} - while(current = current->parent && current->parent); - return current; +tnode_t* btree_root(tnode_t *node) +{ + tnode_t* current = node; + while((current = current->parent) && current->parent); + return current; +} + +void btree_insert(tnode_t *root, tnode_t *new_node) +{ + tnode_t *current = root; + int rootdiff = compare(current->type, ¤t->vi, &new_node->vi); + bool left = current->left_child != NULL; + bool right = current->right_child != NULL; + + if (!rootdiff) return; + + if (left) + { + if (rootdiff < 0) + btree_insert(current->left_child, new_node); + } + else + { + if (rootdiff < 0) + { + current->left_child = new_node; + new_node->parent = current; + } + } + if (right) + { + if (rootdiff > 0) + btree_insert(current->right_child, new_node); + } + else + { + if (rootdiff > 0) + { + current->right_child = new_node; + new_node->parent = current; + } + } +} + +void btree_delete(tnode_t *root, void *data) +{ + int rootdiff = compare(root->type, &root->vi, data); + bool left = root->left_child; + bool right = root->right_child; + tnode_t **position_in_parent_ptr = NULL; + if (root->parent && root->parent->left_child == root) + position_in_parent_ptr = &root->parent->left_child; + if (root->parent && root->parent->right_child == root) + position_in_parent_ptr = &root->parent->right_child; + + if (rootdiff < 0 && left) + { + btree_delete(root->left_child, data); + } + if (rootdiff > 0 && right) + { + btree_delete(root->right_child, data); + } + if (!rootdiff) + { + if (left && !right) + { + root->left_child->parent = root->parent; + if (position_in_parent_ptr) + *position_in_parent_ptr = root->left_child; + } + if (!left && right) + { + root->right_child->parent = root->parent; + if (position_in_parent_ptr) + *position_in_parent_ptr = root->right_child; + } + if (left && right) + { + tnode_t *walker = root->right_child; + while (walker->left_child) walker = walker->left_child; + if (position_in_parent_ptr) + *position_in_parent_ptr = walker; + walker->parent = root->parent; + } + } +} + +tnode_t* btree_find(tnode_t *current, void *data) +{ + int currentdiff = compare(current->type, ¤t->vi, data); + if (!currentdiff) return current; + if (currentdiff < 0) + if (current->left_child) btree_find(current->left_child, data); + else return NULL; + else + if (current->right_child) btree_find(current->right_child, data); + else return NULL; } #endif //TREE_H