#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "/u1/h0/jkinne/public_html/cs202-f2019/code/data_structures/binary_tree/bst.h"
// find where word is in the tree and return its parent
// if not in the tree then return what would be parent if
// we inserted
tree_t *bst_lookup_parent(tree_t *root, void *data, int data_size) {
if (root == NULL) return NULL;
// look for word in the tree. keep track of current
// and its parent as we go.
tree_t *current=root, *parent = NULL;
while (current != NULL) {
int result = current->compare(data, data_size, current->data, current->data_size);
if (result == 0) return parent; // found the word in the tree
parent = current;
if (result < 0)
current = current->left;
else
current = current->right;
}
return parent;
}
// make a new node - allocate memory, set right/left = NULL,
// put in word and number
tree_t *bst_make_node(void *data, int data_size,
int (*compare)(void *, int, void *, int),
void (*print)(void *, int, int),
void (*free)(void *, int)) {
// create a new node
tree_t *t = (tree_t *) malloc(sizeof(tree_t));
assert(t != NULL);
t->left = t->right = NULL;
t->data = malloc(data_size);
memcpy(t->data, data, data_size);
t->data_size = data_size;
t->compare = compare;
t->print = print;
t->free = free;
return t;
}
// free memory from the node
void bst_free_node(tree_t *t) {
if (t == NULL) return;
if (t->data != NULL) t->free(t->data, t->data_size);
free(t);
}
// HW42 - if allow_duplicate is non-zero, still do the insert if duplicate, and insert duplicates on left
tree_t *bst_insert(tree_t *root,
void *data, int data_size, unsigned int flags,
int (*compare)(void *, int, void *, int),
void (*print)(void *, int, int),
void (*free)(void *, int)) {
if (data == NULL) return root; // sanity check
tree_t *t = bst_make_node(data, data_size, compare, print, free);
// NULL root is empty tree, so t is now the root, return it
if (root == NULL) return t;
// find where should be inserted (lookup)
tree_t *parent = bst_lookup_parent(root, data, data_size);
if (parent == NULL) {
// root != NULL but parent==NULL means s is in the root
bst_free_node(t);
return root;
}
// there is a parent, let's see...
int result = parent->compare(data, data_size, parent->data, parent->data_size);
if (result < 0 && parent->left == NULL) // put on the left
parent->left = t;
else if (result > 0 && parent->right == NULL) // put on the right
parent->right = t;
else // already in the tree
bst_free_node(t);
// HW42 - check whether node is balanced or not (need max_depth set
// properly in order to do this), and if not balanced o
// AVL rotation(s).
// See https://www.geeksforgeeks.org/avl-tree-set-1-insertion/
/*
note: t has 0 children, it's "balance factor" is 0
loop with z=t, then current = z->parent, as long as z != NULL
for z -
update value for z->max_height
compute z's balance factor: z->left->max_height - z->right->max_height
(careful about if z->left == NULL or z->right == NULL
if (balance_factor(z) == 2 && balance_factor(z->left) == 1) {
tree_t * y = z->left; tree_t *x = y->left;
tree_t * T1, T2, T3, T4 - set them...;
tree_t * z_parent = z->parent;
update everything like on the board;
}
*/
return root;
}
tree_t *bst_lookup(tree_t *root, void *data, int data_size) {
tree_t *current=root;
while (current != NULL) {
int result = current->compare(data, data_size, current->data, current->data_size);
if (result == 0) break;
if (result < 0)
current = current->left;
else
current = current->right;
}
return current;
}
tree_t *bst_delete(tree_t *root, tree_t *p, unsigned int flags) {
// HW42 - needs to be completed
/*
Let p be the node to delete.
Let p_parent be p's parent.
Cases
1) p is a leaf
p_parent->(left or right) = NULL
2) p->left != NULL
p_largest = largest in p->left subtree
put p_largest in p
p_largest->right = p->right
p_largest->left = p->left
somewhere in there, delete(p_largest) recursively
3) p->left == NULL
p_parent->(left or right) = p->right
After that, free p
*/
return root;
}
// helper function for bst_print, prints the tree
// with the # spaces indicating depth
void bst_print__(tree_t *root, int depth) {
if (root == NULL) return;
bst_print__(root->left, depth+1);
root->print(root->data, root->data_size, depth);
bst_print__(root->right, depth+1);
}
// HW42 - modify bst_print so it uses parameters as described in bst.h
void bst_print(tree_t *root, int limit, unsigned int flags) {
bst_print__(root, 0);
}
// HW42 - complete function as described in bst.h
void bst_map(tree_t *root, void (*fun)(tree_t *, void *), void *param) {
}