From: Mike D. Lowis Date: Thu, 18 Apr 2013 01:09:16 +0000 (-0400) Subject: First draft of binary tree implementation X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=6429cd993b7cbef391026e3aa88c50ac79894af0;p=projs%2Flibcds.git First draft of binary tree implementation --- diff --git a/source/buffer/buf.h b/source/buffer/buf.h index 773d34b..483c434 100644 --- a/source/buffer/buf.h +++ b/source/buffer/buf.h @@ -11,6 +11,7 @@ extern "C" { #endif +#include #include /** A structure defining a circular buffer */ diff --git a/source/list/list.h b/source/list/list.h index 5a146c2..80bde49 100644 --- a/source/list/list.h +++ b/source/list/list.h @@ -5,6 +5,7 @@ extern "C" { #endif +#include #include /** A linked list node. */ @@ -30,7 +31,7 @@ typedef struct list_t * * @return A pointer to the newly created list. **/ -extern list_t* list_new(void); +list_t* list_new(void); /** * @brief Creates a new node with given contents. diff --git a/source/tree/tree.c b/source/tree/tree.c new file mode 100644 index 0000000..051ec9b --- /dev/null +++ b/source/tree/tree.c @@ -0,0 +1,169 @@ +/** + @file tree.c + @brief See header for details + $Revision$ + $HeadURL$ + */ +#include +#include "tree.h" + +tree_t* tree_new(tree_cmp_fn_t cmp_fn) +{ + tree_t* tree = (tree_t*)malloc(sizeof(tree_t)); + tree->cmp_fn = (NULL == cmp_fn) ? tree_cmp_ptrs : cmp_fn; + tree->size = 0; + tree->root = NULL; + return tree; +} + +tree_node_t* tree_new_node(void* value) +{ + tree_node_t* node = (tree_node_t*)malloc(sizeof(tree_node_t)); + node->value = value; + node->left = NULL; + node->right = NULL; + return node; +} + +int tree_cmp_ptrs(void* tval,void* fval) +{ + int ret = 0; + if (tval < fval) + ret = -1; + else if (tval > fval) + ret = 1; + return ret; +} + +void tree_free(tree_t* tree, bool free_values) +{ + tree_free_node(tree->root, free_values); + free(tree); +} + +void tree_free_node(tree_node_t* node, bool free_value) +{ + if (node->left != NULL) + tree_free_node(node->left, free_value); + if (node->right != NULL) + tree_free_node(node->right, free_value); + if (free_value) + free(node->value); + free(node); +} + +bool tree_empty(tree_t* tree) +{ + return (tree_size(tree) == 0); +} + +size_t tree_size(tree_t* tree) +{ + return tree->size; +} + +size_t tree_max_size(void) +{ + return (size_t)(-1); +} + +void tree_insert(tree_t* tree, void* value) +{ + bool finished = false; + tree_node_t* node = tree->root; + while(!finished) + { + switch (tree->cmp_fn(node->value, value)) + { + // If the value is already in the tree + case 0: + // Nothing to do because it's already there. + finished = true; + break; + + case -1: + if (NULL == node->right) + { + node->right = tree_new_node( value ); + tree->size++; + finished = true; + } + else + { + node = node->right; + } + break; + + case 1: + if (NULL == node->left) + { + node->left = tree_new_node( value ); + tree->size++; + finished = true; + } + else + { + node = node->left; + } + break; + } + } +} + +void* tree_at(tree_t* tree, void* value) +{ + void* ret_val = NULL; + tree_node_t* node = tree->root; + while(node != NULL) + { + switch (tree->cmp_fn(node->value, value)) + { + case 0: + ret_val = node->value; + node = NULL; + break; + + case -1: + node = node->right; + break; + + case 1: + node = node->left; + break; + } + } + return ret_val; +} + +void tree_erase(tree_t* tree, void* value) +{ + //tree_node_t* prev_node = NULL; + //tree_node_t* curr_node = tree->root; + //while(node != NULL) + //{ + // switch (tree->cmp_fn(node->value, value)) + // { + // case 0: + // ret_val = node->value; + // node = NULL; + // break; + + // case -1: + // node = node->right; + // break; + + // case 1: + // node = node->left; + // break; + // } + //} +} + +void tree_clear(tree_t* tree, bool free_values) +{ + tree->size = 0; + tree_free_node( tree->root, free_values ); + tree->root = NULL; +} + + diff --git a/source/tree/tree.h b/source/tree/tree.h index 401a345..1fe6836 100644 --- a/source/tree/tree.h +++ b/source/tree/tree.h @@ -1,12 +1,156 @@ /** @file tree.h - @brief An implementation of a Red-Black binary tree. + @brief An implementation of a binary tree. $Revision$ $HeadURL$ */ #ifndef TREE_H #define TREE_H +#ifdef __cplusplus +extern "C" { +#endif +#include +#include + +/** A node in a tree */ +typedef struct { + void* value; /*< The value of the node in the tree */ + void* left; /*< Pointer to the left child of the node */ + void* right; /*< Pointer to the right child of the node */ +} tree_node_t; + +/** A comparison function used to compare node values when looking up or + * inserting values + * + * @param tval The "tree" value. The value stored in the tree. + * @param fval The "free" value. The value to be inserted, erased, or looked up. + * + * @return 0 if the values are equal. + * -1 if "tree" value (tval) is less than "free" value (fval). + * 1 if "tree" value (tval) is greater than "free" value (fval). + **/ +typedef int (*tree_cmp_fn_t)(void* tval,void* fval); + +/** A binary tree */ +typedef struct { + tree_cmp_fn_t cmp_fn; /*< Comparison function used to compare values stored in the tree */ + size_t size; /*< The number of elements currently stored in the tree */ + tree_node_t* root; /*< Pointer to the root of the tree */ +} tree_t; + +/** + * @brief Create a new empty binary tree. + * + * @param cmp_fn The function to be used for comparing values. + * + * @return Pointer to the newly created tree. + */ +tree_t* tree_new(tree_cmp_fn_t cmp_fn); + +/** + * @brief Create a new tree node with the provided value. + * + * @param value The value to be stored in the node. + * + * @return Pointer to the newly created node. + */ +tree_node_t* tree_new_node(void* value); + + +/** + * @brief Compare the raw pointer values provided. + * + * This function is the comparison function used if the user does not provide a + * function when the tree is initialized. + * + * @param tval The "tree" value. The value stored in the tree. + * @param fval The "free" value. The value to be inserted, erased, or looked up. + * + * @return 0 if the values are equal. + * -1 if "tree" value (tval) is less than "free" value (fval). + * 1 if "tree" value (tval) is greater than "free" value (fval). + */ +int tree_cmp_ptrs(void* tval,void* fval); + +/** + * @brief Free the tree and all it's nodes. + * + * @param tree The tree to be freed. + * @param free_values Whether the value of each node should also be freed. + */ +void tree_free(tree_t* tree, bool free_values); + +/** + * @brief Frees the tree node. + * + * @param node The node to be freed. + * @param free_value Whether the value of the node should also be freed. + */ +void tree_free_node(tree_node_t* node, bool free_value); + +/** + * @brief Return whether the tree is empty or not. + * + * @param tree The tree in question. + * + * @return Whether the tree is empty or not. + */ +bool tree_empty(tree_t* tree); + +/** + * @brief Return the number of elements currently in the tree. + * + * @param tree The tree in question. + * + * @return The number of elements currently in the tree. + */ +size_t tree_size(tree_t* tree); + +/** + * @brief Return the maximum number of elements that can be stored in a tree. + * + * @return The maximum number of elements that can be stored in a tree. + */ +size_t tree_max_size(void); + +/** + * @brief Insert the given element in the given tree. + * + * @param tree The tree in which the element will be inserted. + * @param value The value to insert. + */ +void tree_insert(tree_t* tree, void* value); + +/** + * @brief Lookup the provided value in the provided tree. + * + * @param tree The tree in question. + * @param value Pointer to the value to find. + * + * @return Pointer to the matching value or NULL if none found. + */ +void* tree_at(tree_t* tree, void* value); + +/** + * @brief Erase from the tree the first element matching the provided value. + * + * @param tree The tree from which the value will be removed. + * @param value Pointer to the value to erase. + */ +void tree_erase(tree_t* tree, void* value); + +/** + * @brief Erase all values in the tree. + * + * @param tree The tree to clear. + * @param free_values Whether the values should be freed or not. + */ +void tree_clear(tree_t* tree, bool free_values); + +#ifdef __cplusplus +} +#endif #endif /* TREE_H */ diff --git a/source/vector/vec.h b/source/vector/vec.h index aa9d2d7..1ef331e 100644 --- a/source/vector/vec.h +++ b/source/vector/vec.h @@ -7,6 +7,7 @@ #ifndef VEC_H #define VEC_H +#include #include #include #include diff --git a/tests/test_tree.cpp b/tests/test_tree.cpp new file mode 100644 index 0000000..8e12564 --- /dev/null +++ b/tests/test_tree.cpp @@ -0,0 +1,16 @@ +// Unit Test Framework Includes +#include "UnitTest++.h" +#include +#include + +// File To Test +#include "tree.h" + +using namespace UnitTest; + +//----------------------------------------------------------------------------- +// Begin Unit Tests +//----------------------------------------------------------------------------- +namespace { + +}