1
0
Fork 0
C_lib/trees/binary_tree.c~

145 lines
4.3 KiB
C

/* This file contains the function implementations for binary trees. */
#include "binary_tree.h"
#define TREE_SUCCESS_CODE 0
#define TREE_FAILURE_CODE 1
#define TREE_COMPARISON_SMALLER_THAN -1
#define TREE_COMPARISON_EQUAL_TO 0
#define TREE_COMPARISON_LARGER_THAN 1
/* This function initializes a new empty tree node, will return NULL on failure. */
tree_node_t* initialize_tree_node() {
/* Attempt to allocate and return the result. */
tree_node_t *result = (tree_node_t*) malloc(sizeof(tree_node_t));
if (result == NULL)
return NULL;
result->right = NULL;
result->left = NULL;
result->data = NULL;
return result;
}
/* This function initializes a new tree node and attempts to store the given data within, will return NULL on failure. */
tree_node_t* initialize_tree_node_store(void *data) {
/* Attempt to allocate. */
tree_node_t *result = (tree_node_t*) malloc(sizeof(tree_node_t));
/* Check, fill and return. */
if (result == NULL)
return NULL;
result->right = NULL;
result->left = NULL;
result->data = data;
return result;
}
/* This function links a node to the right, will overwrite links! Returns 0 on success and 1 on failure. */
int link_tree_node_right(tree_node_t *parent, tree_node_t *child) {
/* Sanity check. */
if (parent == NULL || child == NULL)
return TREE_FAILURE_CODE;
/* Link and return success. */
parent->right = child;
return TREE_SUCCESS_CODE;
}
/* This function links a node to the left, will overwrite links! Returns 0 on success and 1 on failure. */
int link_tree_node_left(tree_node_t *parent, tree_node_t *child) {
/* Sanity check. */
if (parent == NULL || child == NULL)
return TREE_FAILURE_CODE;
/* Link and return success. */
parent->left = child;
return TREE_SUCCESS_CODE;
}
/* TODO: rewrite iteratively? */
/* This function attempts to free a whole tree (recursively), while not touching the data. */
void free_tree(tree_node_t *root) {
/* Stopping conditions. */
if (root == NULL)
return;
if (root->right == NULL && root->left == NULL) {
free(root);
return;
}
/* Recursive case. */
if (root->right != NULL) {
free_tree(root->right);
root->right = NULL;
}
if (root->left != NULL) {
free_tree(root->left);
root->left = NULL;
}
/* Free the current node. */
free(root);
}
/* TODO: rewrite iteratively? */
/* This function attempts to free a whole tree (recursively), while using free_function to free the data, if the latter is NULL - will use stdlib free. */
void free_tree_data(tree_node_t *root, void (*free_function)()) {
/* Stopping conditions. */
if (root == NULL)
return;
if (root->right == NULL && root->left == NULL) {
if (free_function == NULL)
free(root->data);
else
free_function(root->data);
free(root);
return;
}
/* Recursive case. */
if (root->right != NULL) {
free_tree_data(root->right);
root->right = NULL;
}
if (root->left != NULL) {
free_tree_data(root->left);
root->left = NULL;
}
/* Free the current node. */
if (free_function == NULL)
free(root->data);
else
free_function(root->data);
free(root);
}
/* Note that the implementation disallows duplication! */
/* This function inserts data into the tree, will fail on invalid input. Comparison function should return 0 for equal, 1 for larger than and -1 for less than. */
int insert_node_into_tree(tree_node_t *root, tree_node_t *to_insert, int (*comparison_function)()) {
/* Local variables. */
int comparison_result;
/* Sanity check. */
if (comparison_function == NULL || root == NULL)
return TREE_FAILURE_CODE;
/* Compare. */
comparison_result = (*comparison_function)(root->data, to_insert->data);
/* Check if the value is already there. */
if (comparison_result == TREE_COMPARISON_EQUAL_TO)
return TREE_SUCCESS_CODE;
/* Check if the root is smaller. */
if (comparison_result == TREE_COMPARISON_SMALLER_THAN) {
/* The root is smaller. */
if (root->right == NULL) {
/* Insert to the right. */
root->right = to_insert;
return TREE_SUCCESS_CODE;
}
/* Recurse. */
return insert_node_into_tree(root->right, to_insert, comparison_function);
} else {
/* The root is larger. */
if (root->left == NULL) {
/* Insert to the left. */
root->right = to_insert;
return TREE_SUCCESS_CODE;
}
/* Recurse. */
return insert_node_into_tree(root->left, to_insert, comparison_function);
}
/* Shouldn't ever reach here! */
return TREE_FAILURE_CODE;
}