# binarytree Binary tree with standard leaf operations ## Usage Create the tree. The user is responsible for memory management of the `BinTree` struct. ```c BinTree *tree = malloc(sizeof(BinTree)); ``` After the tree is created, init it. The second argument on `bintree_init()` is an optional memory freeing function pointer with signature `void (*destroy)(void *data)`. Use `free()` from the stdlib if you are creating the data with `malloc()`. If allocation of your data is more complex, you can pass your own memory deallocation function as long as it fits the signature. In this example, we are passing `NULL` because all memory will be stack allocated. ```c bintree_init(tree, NULL); int root = 0; int l1 = 1; int l2 = 2; int r1 = 12; int r2 = 200; ``` Next lets insert our data into the tree. The insert functions signature is `bintree_ins_...(tree, parent, data)`. If you are inserting data at the root of the tree, you may use either `bintree_ins_left()` or `bintree_ins_right()` as long as `NULL` is passed as the parent argument. ```c bintree_ins_left(tree, NULL, &root); bintree_ins_left(tree, tree->root, &l1); bintree_ins_left(tree, tree->root->left, &l2); bintree_ins_right(tree, tree->root->left, &r2); bintree_ins_right(tree, tree->root, &r1); bintree_ins_right(tree, tree->root->right, &r2); bintree_ins_left(tree, tree->root->right, &l1); ``` We can use `bintree_debug_print(tree)` to print a graphical representation of the tree to `stdout` ```plaintext └──0 ├──1 │ ├──2 │ └──200 └──12 ├──1 └──200 ``` To cleanup the tree, first destroy the nodes. If you passed a deallocation function, it will be called on the data member of each node before the node itself is freed. `bintree_destroy()` does not free the tree itself, just the nodes inside of it, hence we must also call `free()` on the tree. ```c bintree_destroy(tree); free(tree); tree = NULL; ``` Here is the entire example: ```c BinTree *tree = malloc(sizeof(BinTree)); bintree_init(tree, NULL); int root = 0; int l1 = 1; int l2 = 2; int r1 = 12; int r2 = 200; bintree_ins_left(tree, NULL, &root); bintree_ins_left(tree, tree->root, &l1); bintree_ins_left(tree, tree->root->left, &l2); bintree_ins_right(tree, tree->root->left, &r2); bintree_ins_right(tree, tree->root, &r1); bintree_ins_right(tree, tree->root->right, &r2); bintree_ins_left(tree, tree->root->right, &l1); bintree_debug_print(tree); bintree_destroy(tree); free(tree); tree = NULL; ``` ## Structs ### BinTree Binary tree struct ```c typedef struct { int size; int (*compare)(const void *a, const void *b); void (*destroy)(void *data); struct BinTreeNode *root; } BinTree; ``` Members: - `size`: How many nodes the tree contains - `compare`: Comparison function between data in two nodes. Currently not used for anything - `destroy`: Optional deallocation function for data inside a node. Typical usage is `NULL` for stack allocated data and `free()` for data created with `malloc()` - `root`: The root node of the tree ### BinTreeNode Node of the tree ```c typedef struct BinTreeNode { void *data; struct BinTreeNode *left; struct BinTreeNode *right; } BinTreeNode; ``` Members: - `data`: void pointer to data the node contains - `left`: left facing leaf of the node - `right`: right facing leaf of the node ## Functions ### bintree_init Initialize the binary tree. User is responsible for freeing memory with `bintree_destroy()`. ```c void bintree_init(BinTree *tree, void (*destroy)(void *data)) ``` ### bintree_destroy Destroys the nodes inside a tree and calls the deallaction function on the data if one was provided. Does not deallocate the tree itself, that is left to the user. ```c void bintree_destroy(BinTree *tree) ``` ### bintree_ins_left Creates a new node containing `data` and inserts it as the left child of `node`. ```c int bintree_ins_left(BinTree *tree, BinTreeNode *node, void *data) ``` ### bintree_ins_right Creates a new node containing `data` and inserts it as the right child of `node`. ```c int bintree_ins_right(BinTree *tree, BinTreeNode *node, void *data) ``` ### bintree_rem_left Removes and deallocates the left child node of `node`. Calls the deallocation function on the data if one was provided. ```c void bintree_rem_left(BinTree *tree, BinTreeNode *node) ``` ### bintree_rem_right Removes and deallocates the right child node of `node`. Calls the deallocation function on the data if one was provided. ```c void bintree_rem_right(BinTree *tree, BinTreeNode *node) ``` ### bintree_debug_print Prints a representation of the tree to stdout. Gets very messy with large trees. ```c void bintree_debug_print(BinTree *tree) ``` ### bintree_is_eob Utility macro that checks if the node is the End Of Branch. ```c #define bintree_is_eob(node) ((node) == NULL) ``` ### bintree_is_leaf Utility macro that checks if a node has children. ```c #define bintree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL) ```