Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Finally got delete working. Worst part of a binary tree ever.

  • Loading branch information...
commit 54c0e2c71d68f2689eba895649fa8a9a18818d33 1 parent d4dbdeb
@zedshaw authored
Showing with 88 additions and 5 deletions.
  1. +68 −5 src/btree.c
  2. +2 −0  src/btree.h
  3. +18 −0 tests/btree_tests.c
View
73 src/btree.c
@@ -41,13 +41,14 @@ void btree_destroy(btree_t *map)
}
-static inline btree_node_t *btree_node_create(void *key, void *data)
+static inline btree_node_t *btree_node_create(btree_node_t *parent, void *key, void *data)
{
btree_node_t *node = calloc(1, sizeof(btree_node_t));
check_mem(node);
node->key = key;
node->data = data;
+ node->parent = parent;
return node;
error:
@@ -63,13 +64,13 @@ static inline void btree_setnode(btree_t *map, btree_node_t *node, void *key, vo
if(node->left) {
btree_setnode(map, node->left, key, data);
} else {
- node->left = btree_node_create(key, data);
+ node->left = btree_node_create(node, key, data);
}
} else {
if(node->right) {
btree_setnode(map, node->right, key, data);
} else {
- node->right = btree_node_create(key, data);
+ node->right = btree_node_create(node, key, data);
}
}
}
@@ -79,7 +80,7 @@ int btree_set(btree_t *map, void *key, void *data)
{
if(map->root == NULL) {
// first so just make it and get out
- map->root = btree_node_create(key, data);
+ map->root = btree_node_create(NULL, key, data);
check_mem(map->root);
} else {
btree_setnode(map, map->root, key, data);
@@ -143,7 +144,69 @@ static inline int btree_traverse_nodes(btree_node_t *node, btree_traverse_cb tra
int btree_traverse(btree_t *map, btree_traverse_cb traverse_cb)
{
if(map->root) {
- btree_traverse_nodes(map->root, traverse_cb);
+ return btree_traverse_nodes(map->root, traverse_cb);
}
+
+ return 0;
+}
+
+static inline btree_node_t *btree_find_min(btree_node_t *node)
+{
+ while(node->left) {
+ node = node->left;
+ }
+
+ return node;
+}
+
+static inline void btree_replace_node_in_parent(btree_t *map, btree_node_t *node, btree_node_t *new_value)
+{
+ if(node->parent) {
+ if(node == node->parent->left) {
+ node->parent->left = new_value;
+ } else {
+ node->parent->right = new_value;
+ }
+ } else {
+ // this is the root so gotta change it
+ map->root = new_value;
+ }
+
+ if(new_value) {
+ new_value->parent = node->parent;
+ }
+}
+
+static inline btree_node_t *btree_node_delete(btree_t *map, btree_node_t *node, void *key)
+{
+ int cmp = map->compare(node->key, key);
+
+ if(cmp < 0) {
+ return btree_node_delete(map, node->left, key);
+ } else if(cmp > 0) {
+ return btree_node_delete(map, node->right, key);
+ } else {
+ if(node->left && node->right) {
+ btree_node_t *successor = btree_find_min(node);
+ btree_replace_node_in_parent(map, node, successor->right);
+ } if(node->left) {

This line looks wrong, should be it be the following (missing else)?

} else if (node->left) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ btree_replace_node_in_parent(map, node, node->left);
+ } else if(node->right) {
+ btree_replace_node_in_parent(map, node, node->right);
+ } else {
+ btree_replace_node_in_parent(map, node, NULL);
+ }
+
+ return node;
+ }
+}
+
+void *btree_delete(btree_t *map, void *key)
+{
+ btree_node_t *node = btree_node_delete(map, map->root, key);
+ void *data = node->data;
+ free(node);
+
+ return data;
}
View
2  src/btree.h
@@ -10,6 +10,7 @@ typedef struct btree_node_t {
struct btree_node_t *left;
struct btree_node_t *right;
+ struct btree_node_t *parent;
} btree_node_t;
typedef struct btree_t {
@@ -28,5 +29,6 @@ void *btree_get(btree_t *map, void *key);
int btree_traverse(btree_t *map, btree_traverse_cb traverse_cb);
+void *btree_delete(btree_t *map, void *key);
#endif
View
18 tests/btree_tests.c
@@ -70,6 +70,24 @@ char *test_get_set_traverse()
mu_assert(rc == 1, "Failed to traverse.");
mu_assert(traverse_called == 2, "Wrong count traverse for fail.");
+ bstring deleted = (bstring)btree_delete(map, test1);
+ mu_assert(deleted != NULL, "Got NULL on delete.");
+ mu_assert(deleted == expect1, "Should get test1");
+ result = btree_get(map, test1);
+ mu_assert(result == NULL, "Should delete.");
+
+ deleted = (bstring)btree_delete(map, test2);
+ mu_assert(deleted != NULL, "Got NULL on delete.");
+ mu_assert(deleted == expect2, "Should get test2");
+ result = btree_get(map, test2);
+ mu_assert(result == NULL, "Should delete.");
+
+ deleted = (bstring)btree_delete(map, test3);
+ mu_assert(deleted != NULL, "Got NULL on delete.");
+ mu_assert(deleted == expect3, "Should get test2");
+ result = btree_get(map, test3);
+ mu_assert(result == NULL, "Should delete.");
+
btree_destroy(map);
bdestroy(test1);
bdestroy(test2);
Please sign in to comment.
Something went wrong with that request. Please try again.