From 755eedde3ff12dad82c5a4cff0b6d9611150e630 Mon Sep 17 00:00:00 2001 From: jussi Date: Wed, 6 Nov 2019 23:17:28 +0200 Subject: [PATCH] lib: add binary search tree implementation --- src/include/tc_common.h | 19 +++++++++++++++ src/lib/tc_common.c | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/include/tc_common.h b/src/include/tc_common.h index 2621153..504f809 100644 --- a/src/include/tc_common.h +++ b/src/include/tc_common.h @@ -15,7 +15,9 @@ extern "C" { // Tagged union of data types for simulating function overloading enum tc_data_types { + TC_TYPE_NONE, TC_TYPE_INT, + TC_TYPE_UINT, TC_TYPE_DOUBLE, TC_TYPE_STRING, TC_TYPE_STRING_ARR @@ -25,6 +27,7 @@ typedef struct { enum tc_data_types data_type; union { int64_t int_value; + uint64_t uint_value; double double_value; char *string_value; }; @@ -44,6 +47,22 @@ char **tc_str_arr_dup(uint16_t str_count, char **const strings); // Deallocate string array void tc_str_arr_free(uint16_t str_count, char **strings); +// Binary search tree whose left node contains the smaller value +typedef struct tc_bin_node_ { + void *key; + void *value; + + struct tc_bin_node_ *left; + struct tc_bin_node_ *right; +} tc_bin_node_t; + +// Create a new node with key and data in the appropriate position +tc_bin_node_t *tc_bin_node_insert(tc_bin_node_t* node, void *key, void *value); +// Find the value associated with the key +void *tc_bin_node_find_value(tc_bin_node_t *node, void *key); +// Destroy a node and its children +void tc_bin_node_destroy(tc_bin_node_t *node); + #ifdef __cplusplus } #endif diff --git a/src/lib/tc_common.c b/src/lib/tc_common.c index 1fc5cab..22a8b2f 100644 --- a/src/lib/tc_common.c +++ b/src/lib/tc_common.c @@ -18,3 +18,56 @@ void tc_str_arr_free(uint16_t str_count, char **strings) { } free(strings); } + +static tc_bin_node_t *new_bin_node(void *key, void *value) { + tc_bin_node_t *new_node = calloc(1, sizeof(tc_bin_node_t)); + new_node->key = key; + new_node->value = value; + return new_node; +} + +static void single_destroy(tc_bin_node_t *node) { + free(node); +} + +static void traverse_postorder(tc_bin_node_t *node, void (*func)(tc_bin_node_t*)) { + if (node->left) { + traverse_postorder(node, func); + } + if (node->right) { + traverse_postorder(node, func); + } + func(node); +} + +tc_bin_node_t *tc_bin_node_insert(tc_bin_node_t *node, void *key, void *value) { + if (node == NULL) { + return new_bin_node(key, value); + } + + if (key < node->key) { + node->left = tc_bin_node_insert(node->left, key, value); + } + else if (key > node->key) { + node->right = tc_bin_node_insert(node->right, key, value); + } + return node; +} + +void *tc_bin_node_find_value(tc_bin_node_t *node, void *key) { + if (node == NULL) { + return NULL; + } + if (node->key == key) { + return node->value; + } + + if (node->key < key) { + return tc_bin_node_find_value(node->right, key); + } + return tc_bin_node_find_value(node->left, key); +} + +void tc_bin_node_destroy(tc_bin_node_t *node) { + traverse_postorder(node, &single_destroy); +}