====== binarytree ======
Binary tree with standard leaf operations
===== Usage =====
Create the tree. The user is responsible for memory management of the ''%%BinTree%%'' struct.
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.
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.
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%%''
└──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.
bintree_destroy(tree);
free(tree);
tree = NULL;
Here is the entire example:
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
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
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()%%''.
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.
void bintree_destroy(BinTree *tree)
==== bintree_ins_left ====
Creates a new node containing ''%%data%%'' and inserts it as the left child of ''%%node%%''.
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%%''.
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.
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.
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.
void bintree_debug_print(BinTree *tree)
==== bintree_is_eob ====
Utility macro that checks if the node is the End Of Branch.
#define bintree_is_eob(node) ((node) == NULL)
==== bintree_is_leaf ====
Utility macro that checks if a node has children.
#define bintree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL)