#include #include #include #include "bstree.h" typedef struct bstreenode { char *key; void *value; struct bstreenode *left_child; struct bstreenode *right_child; } BstreeNode; typedef struct { BstreeNode *root; } Bstree; static void *bstree_find_min_helper(BstreeNode *node); /* create a new bstree by creating its container object */ void *new_bstree() { Bstree *tree = (Bstree *)malloc(sizeof(Bstree)); tree->root = NULL; return tree; } // free a subtree by recursively freeing its left and right subtrees, // and then freeing the root node of the subtree static void recursive_free_bstree(BstreeNode *bn) { if (bn == NULL) return; if (bn->left_child != NULL) recursive_free_bstree(bn->left_child); if (bn->right_child != NULL) recursive_free_bstree(bn->right_child); free(bn); return; } // free a bstree by deleting all the nodes in the tree and then freeing // the container object void free_bstree(void *tree) { Bstree *b = (Bstree *)tree; recursive_free_bstree(b->root); free(b); return; } static BstreeNode *tree_insert_helper(BstreeNode *current_node, char *key, void *value) { if (current_node == NULL) { // create a new leaf node current_node = (BstreeNode *)malloc(sizeof(BstreeNode)); current_node->left_child = NULL; current_node->right_child = NULL; current_node->key = key; current_node->value = value; } else { int compare_result = strcmp(key, current_node->key); if (compare_result < 0) current_node->left_child = tree_insert_helper(current_node->left_child, key, value); else if (compare_result > 0) current_node->right_child = tree_insert_helper(current_node->right_child, key, value); // else set key to new value else current_node->value = value; } return current_node; } void bstree_insert(void *binary_tree, char *key, void *value) { Bstree *tree = (Bstree *)binary_tree; tree->root = tree_insert_helper(tree->root, key, value); } static void *tree_find_helper(BstreeNode *current_node, void *key) { if (current_node == NULL) return 0; int compare_result = strcmp(key, current_node->key); if (compare_result < 0) return tree_find_helper(current_node->left_child, key); else if (compare_result > 0) return tree_find_helper(current_node->right_child, key); else // key has been found--return the value of the node return current_node->value; } void *bstree_find(void *binary_tree, char *key) { Bstree *tree = (Bstree *)binary_tree; return tree_find_helper(tree->root, key); } // delete a node with the indicated key from the tree. Note that we pass // a pointer to the node's position in the tree, rather than the node // itself. This allows us to do an in-place modification of the node if // necessary. static void *bstree_delete_helper(BstreeNode **bn, char *key) { void *return_value; BstreeNode *node = *bn; if (node == NULL) return NULL; // Item not found; do nothing if (strcmp(key, node->key) < 0) return bstree_delete_helper(&node->left_child, key); else if (strcmp(key, node->key) > 0) return bstree_delete_helper(&node->right_child, key); // else key found so do deletion else if ((node->left_child != NULL) && (node->right_child != NULL)) { // two child case--find smallest element in right subtree and promote // it to this node. Then recursively remove the smallest element in the // right subtree BstreeNode *smallest = bstree_find_min_helper(node->right_child); return_value = node->value; node->key = smallest->key; node->value = smallest->value; bstree_delete_helper(&node->right_child, smallest->key); return return_value; } else { return_value = node->value; if (node->left_child != NULL) *bn = node->left_child; else *bn = node->right_child; // works even if right_child is NULL free(node); return return_value; } } /* delete the given key from the tree and return its value. */ void *bstree_delete(void *tree, char *key) { Bstree *b = (Bstree *)tree; return bstree_delete_helper(&b->root, key); } static void *bstree_find_min_helper(BstreeNode *node) { if (node == NULL) return NULL; while (node->left_child != NULL) node = node->left_child; return node; } /* return the value of the minimum key in the tree */ void *bstree_find_min(void *tree) { Bstree *b = (Bstree *)tree; return bstree_find_min_helper(b->root); } /* return the value of the maximum key in the tree */ void *bstree_find_max(void *tree) { Bstree *b = (Bstree *)tree; BstreeNode *bn; if (b->root == NULL) return NULL; bn = b->root; while (bn->right_child != NULL) bn = bn->right_child; return bn; } void *bstree_root(void *tree) { Bstree *b = (Bstree *)tree; return b->root; } void *bstree_left(void *node) { BstreeNode *bn = (BstreeNode *)node; return bn->left_child; } void *bstree_right(void *node) { BstreeNode *bn = (BstreeNode *)node; return bn->right_child; } char *bstree_key(void *node) { BstreeNode *bn = (BstreeNode *)node; return bn->key; } void *bstree_value(void *node) { BstreeNode *bn = (BstreeNode *)node; return bn->value; }