]> git.mdlowis.com Git - archive/carl.git/commitdiff
Added binary search tree implementation to the data structures folder
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 27 Jun 2015 20:38:58 +0000 (16:38 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 27 Jun 2015 20:38:58 +0000 (16:38 -0400)
source/data/bstree.c [new file with mode: 0644]
source/data/bstree.h
tests/data/bstree.c [new file with mode: 0644]
tests/main.c

diff --git a/source/data/bstree.c b/source/data/bstree.c
new file mode 100644 (file)
index 0000000..2ba4eeb
--- /dev/null
@@ -0,0 +1,60 @@
+#include <data/bstree.h>
+
+void bstree_init(bstree_t* tree, bstree_cmpfn_t cmpfn, bool allow_dups)
+{
+    tree->root = NULL;
+    tree->cmpfn = cmpfn;
+    tree->allow_dups = allow_dups;
+}
+
+bool bstree_empty(bstree_t* tree)
+{
+    return (tree->root == NULL);
+}
+
+static size_t subtree_size(bstree_node_t* node)
+{
+    if (node == NULL)
+        return 0;
+    else
+        return (1 + subtree_size(node->left) + subtree_size(node->right));
+}
+
+size_t bstree_size(bstree_t* tree)
+{
+    return subtree_size(tree->root);
+}
+
+static bstree_node_t** find_node(bstree_cmpfn_t cmpfn, bstree_node_t** root, bstree_node_t* node, bool allow_dups)
+{
+    bstree_node_t** curr = root;
+    while(*curr != NULL) {
+        int cmp = cmpfn(node, *curr);
+        if (cmp < 0)
+            curr = &((*curr)->left);
+        else if (cmp > 0)
+            curr = &((*curr)->right);
+        else if (allow_dups)
+            curr = &((*curr)->right);
+        else
+            break;
+    }
+    return curr;
+}
+
+void bstree_insert(bstree_t* tree, bstree_node_t* node)
+{
+    bstree_node_t** curr = find_node(tree->cmpfn, &(tree->root), node, tree->allow_dups);
+    if (*curr == NULL) {
+        *curr = node;
+        node->left = NULL;
+        node->right = NULL;
+    }
+}
+
+bstree_node_t* bstree_lookup(bstree_t* tree, bstree_node_t* node)
+{
+    bstree_node_t** curr = find_node(tree->cmpfn, &(tree->root), node, false);
+    return *curr;
+}
+
index 4beb87c606a0229d768f236c25a08546291c48f5..b44ac94b4673c187004e0d03c2ba9f86c88649f7 100644 (file)
@@ -4,17 +4,22 @@
 #ifndef BSTREE_H
 #define BSTREE_H
 
+#include <libc.h>
+
 typedef struct bstree_node_t {
-    struct bstree_node_t* parent;
     struct bstree_node_t* left;
     struct bstree_node_t* right;
 } bstree_node_t;
 
+typedef int (*bstree_cmpfn_t)(bstree_node_t* a, bstree_node_t* b);
+
 typedef struct {
     bstree_node_t* root;
+    bstree_cmpfn_t cmpfn;
+    bool allow_dups;
 } bstree_t;
 
-void bstree_init(bstree_t* bstree);
+void bstree_init(bstree_t* bstree, bstree_cmpfn_t cmpfn, bool allow_dups);
 
 bool bstree_empty(bstree_t* bstree);
 
@@ -24,12 +29,4 @@ void bstree_insert(bstree_t* bstree, bstree_node_t* node);
 
 bstree_node_t* bstree_lookup(bstree_t* bstree, bstree_node_t* node);
 
-bool bstree_node_hasnext(bstree_node_t* node);
-
-bstree_node_t* bstree_node_next(bstree_node_t* node);
-
-bool bstree_node_hasprev(bstree_node_t* node);
-
-bstree_node_t* bstree_node_prev(bstree_node_t* node);
-
 #endif /* BSTREE_H */
diff --git a/tests/data/bstree.c b/tests/data/bstree.c
new file mode 100644 (file)
index 0000000..f05a703
--- /dev/null
@@ -0,0 +1,146 @@
+
+// Unit Test Framework Includes
+#include "atf.h"
+
+// File To Test
+#include <data/bstree.h>
+
+typedef struct {
+    bstree_node_t node;
+    int val;
+} int_node_t;
+
+int compare(bstree_node_t* a, bstree_node_t* b)
+{
+    int_node_t* nodea = container_of(a, int_node_t, node);
+    int_node_t* nodeb = container_of(b, int_node_t, node);
+    return (nodea->val < nodeb->val) ? -1 : (nodea->val > nodeb->val) ? 1 : 0;
+}
+
+//-----------------------------------------------------------------------------
+// Begin Unit Tests
+//-----------------------------------------------------------------------------
+TEST_SUITE(BSTree) {
+    //-------------------------------------------------------------------------
+    // bstree_init
+    //-------------------------------------------------------------------------
+    TEST(Verify_bstree_init_should_init_the_tree)
+    {
+        bstree_t tree;
+        bstree_init(&tree, NULL, true);
+        CHECK(tree.root == NULL);
+        CHECK(tree.cmpfn == NULL);
+        CHECK(tree.allow_dups == true);
+    }
+
+    //-------------------------------------------------------------------------
+    // bstree_empty
+    //-------------------------------------------------------------------------
+    TEST(Verify_bstree_empty_should_return_true_if_the_tree_is_empty)
+    {
+        bstree_t tree = { 0, 0, 0 };
+        CHECK(bstree_empty(&tree));
+    }
+
+    TEST(Verify_bstree_empty_should_return_false_if_the_tree_is_not_empty)
+    {
+        bstree_t tree = { (bstree_node_t*)0x1234, NULL, false };
+        CHECK(!bstree_empty(&tree));
+    }
+
+    //-------------------------------------------------------------------------
+    // bstree_size
+    //-------------------------------------------------------------------------
+    TEST(Verify_bstree_size_should_return_0_for_empty_tree)
+    {
+        bstree_t tree = { 0, 0, 0 };
+        CHECK(0 == bstree_size(&tree));
+    }
+
+    TEST(Verify_bstree_size_should_return_1)
+    {
+        bstree_node_t node1 = { NULL, NULL };
+        bstree_t tree = { &node1, NULL, false };
+        CHECK(1 == bstree_size(&tree));
+    }
+
+    TEST(Verify_bstree_size_should_return_2)
+    {
+        bstree_node_t node2 = { NULL, NULL };
+        bstree_node_t node1 = { &node2, NULL };
+        bstree_t tree = { &node1, NULL, false };
+        CHECK(2 == bstree_size(&tree));
+    }
+
+    TEST(Verify_bstree_size_should_return_3)
+    {
+        bstree_node_t node3 = { NULL, NULL };
+        bstree_node_t node2 = { NULL, NULL };
+        bstree_node_t node1 = { &node2, &node3 };
+        bstree_t tree = { &node1, NULL, false };
+        CHECK(3 == bstree_size(&tree));
+    }
+
+    //-------------------------------------------------------------------------
+    // bstree_insert
+    //-------------------------------------------------------------------------
+    TEST(Verify_bstree_insert_should_insert_into_empty_tree)
+    {
+        int_node_t node = { {0,0}, 42 };
+        bstree_t tree = { NULL, compare, false };
+        bstree_insert(&tree, &(node.node));
+        CHECK(tree.root = &(node.node));
+    }
+
+    TEST(Verify_bstree_insert_should_insert_to_the_left)
+    {
+        int_node_t node1 = { {0,0}, 42 };
+        int_node_t node2 = { {0,0}, 41 };
+        bstree_t tree = { &(node1.node), compare, false };
+        bstree_insert(&tree, &(node2.node));
+        CHECK(tree.root->left = &(node2.node));
+    }
+
+    TEST(Verify_bstree_insert_should_insert_to_the_right)
+    {
+        int_node_t node1 = { {0,0}, 42 };
+        int_node_t node2 = { {0,0}, 43 };
+        bstree_t tree = { &(node1.node), compare, false };
+        bstree_insert(&tree, &(node2.node));
+        CHECK(tree.root->right = &(node2.node));
+    }
+
+    //-------------------------------------------------------------------------
+    // bstree_lookup
+    //-------------------------------------------------------------------------
+    TEST(Verify_bstree_lookup_should_not_find_the_item_in_an_empty_tree)
+    {
+        int_node_t node1 = { {0,0}, 42 };
+        bstree_t tree = { NULL, compare, false };
+        CHECK(bstree_lookup(&tree, &(node1.node)) == NULL);
+    }
+
+    TEST(Verify_bstree_lookup_should_find_the_item_at_the_root)
+    {
+        int_node_t node1 = { {0,0}, 42 };
+        bstree_t tree = { &(node1.node), compare, false };
+        CHECK(bstree_lookup(&tree, &(node1.node)) == &(node1.node));
+    }
+
+    TEST(Verify_bstree_lookup_should_find_the_item_to_the_left)
+    {
+        int_node_t node2 = { {0,0}, 41 };
+        int_node_t node1 = { {&(node2.node),0}, 42 };
+        bstree_t tree = { &(node1.node), compare, false };
+        CHECK(bstree_lookup(&tree, &(node2.node)) == &(node2.node));
+    }
+
+    TEST(Verify_bstree_lookup_should_find_the_item_to_the_right)
+    {
+        int_node_t node2 = { {0,0}, 43 };
+        int_node_t node1 = { {0,&(node2.node)}, 42 };
+        bstree_t tree = { &(node1.node), compare, false };
+        CHECK(bstree_lookup(&tree, &(node2.node)) == &(node2.node));
+    }
+
+}
index 11ce75b2642d6738ce19d3518dc5e2da14d24ca4..a6ef5433beffbd29eedf128b19466da682b1a6d2 100644 (file)
@@ -7,5 +7,6 @@ void main(int argc, char** argv)
     (void)argv;
     RUN_EXTERN_TEST_SUITE(RefCount);
     RUN_EXTERN_TEST_SUITE(SList);
+    RUN_EXTERN_TEST_SUITE(BSTree);
     exit(PRINT_TEST_RESULTS());
 }