#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; typedef struct tnode_ { int type; union { int vi; unsigned int vui; char vc; float vf; double vd; char *vcp; void *vptr; }; tnode_ptr parent; tnode_ptr left_child; tnode_ptr right_child; } tnode_t; int compare(int type, void *left, void *right) { 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; } } 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