Prototype: binary_tree_t *binary_tree_node(binary_tree_t *parent, int value);
Where parent is a pointer to the parent node of the node to create
And value is the value to put in the new node
When created, a node does not have any child
Your function must return a pointer to the new node, or NULL on failure
Task 1. Insert left
Write a function that inserts a node as the left-child of another node
Prototype: binary_tree_t *binary_tree_insert_left(binary_tree_t *parent, int value);
Where parent is a pointer to the node to insert the left-child in
And value is the value to store in the new node
Your function must return a pointer to the created node, or NULL on failure or if parent is NULL
If parent already has a left-child, the new node must take its place,
and the old left-child must be set as the left-child of the new node.
Task 2. Insert right
Write a function that inserts a node as the right-child of another node
Prototype: binary_tree_t *binary_tree_insert_right(binary_tree_t *parent, int value);
Where parent is a pointer to the node to insert the right-child in
And value is the value to store in the new node
Your function must return a pointer to the created node, or NULL on failure or if parent is NULL
If parent already has a right-child, the new node must take its place,
and the old right-child must be set as the right-child of the new node.
Task 3. Delete
Write a function that deletes an entire binary tree
Where tree is a pointer to the root node of the tree to traverse
And func is a pointer to a function to call for each node.
The value in the node must be passed as a parameter to this function.
If tree or func is NULL, do nothing
Task 7. In-order traversal
Write a function that goes through a binary tree using in-order traversal
Where tree is a pointer to the root node of the tree to traverse
And func is a pointer to a function to call for each node.
The value in the node must be passed as a parameter to this function.
If tree or func is NULL, do nothing
Task 8. Post-order traversal
Write a function that goes through a binary tree using post-order traversal
Where tree is a pointer to the root node of the tree to traverse
And func is a pointer to a function to call for each node.
The value in the node must be passed as a parameter to this function.
If tree or func is NULL, do nothing
Task 9. Height
Write a function that measures the height of a binary tree
Where tree is a pointer to the root node of the tree to count the number of leaves
If tree is NULL, the function must return 0
A NULL pointer is not a leaf
Task 13. Nodes
Write a function that counts the nodes with at least 1 child in a binary tree
Where tree is a pointer to the root node of the tree to count the number of nodes
If tree is NULL, the function must return 0
A NULL pointer is not a node
Task 14. Balance factor
Write a function that measures the balance factor of a binary tree
Prototype: int binary_tree_balance(const binary_tree_t *tree);
Where tree is a pointer to the root node of the tree to measure the balance factor
If tree is NULL, return 0
Task 15. Is full
Write a function that checks if a binary tree is full
Prototype: int binary_tree_is_full(const binary_tree_t *tree);
Where tree is a pointer to the root node of the tree to check
If tree is NULL, your function must return 0
Task 16. Is perfect
Write a function that checks if a binary tree is perfect
Prototype: int binary_tree_is_perfect(const binary_tree_t *tree);
Where tree is a pointer to the root node of the tree to check
If tree is NULL, your function must return 0
Where node is a pointer to the node to find the sibling
Your function must return a pointer to the sibling node
If node is NULL or the parent is NULL, return NULL
If node has no sibling, return NULL
Where node is a pointer to the node to find the uncle
Your function must return a pointer to the uncle node
If node is NULL, return NULL
If node has no uncle, return NULL