Do not implement a class yet. We need these functions to be able to easily implement multiple classes.
First, let's design a tree_node structure:
In addition to the usual item, left, and right, we need to keep track of the "balance factor".
balance factor is calculated as the height of the left subtree minus the height of the right subtree.
But we do not want to be calculating the height of left and right subtrees (by counting the nodes all the way down to the leaves) every time we need the balance factor. So, we need to keep track of the heights "on the fly" by updating the height (by looking at the heights of the left and right children) each time insertion and deletions are made. We can easily calculate the balance factor by subtracting the height of the right child from the height of the left child.
Do not simply increment (or decrement) the height after an insertion (or deletion.) This will not work.
template <typename T> struct tree_node{ T _item; tree_node<T>* _left; tree_node<T>* _right; int _height; int balance_factor(){ //balance factor = height of the left subtree
// - the height of the right subtree //a NULL child has a height of -1 //a leaf has a height of 0 } int height(){ // Height of a node is 1 + height of the "taller" child //A leaf node has a height of zero: 1 + max(-1,-1) } int update_height(){ //set the _height member variable (call height();) } tree_node(T item=T(), tree_node* left=NULL,
tree_node* right=NULL): _item(item), _left(left), _right(right) { //don't forget to set the _height. } friend ostream& operator <<(ostream& outs,
const tree_node<T>& t_node){ outs<<"|"<<t_node._item<<"|"; } };
Implement the following functions for a Binary Search Tree:
template <typename T> void tree_insert(tree_node<T>* &root, const T& insert_me); template <typename T> tree_node<T>* tree_search(tree_node<T>* root, const T& target); template <typename T> bool tree_search(tree_node<T>* root, const T& target, tree_node<T>* &found_ptr); template<typename T> void tree_print(tree_node<T>* root, int depth=0, ostream& outs=cout); template<typename T> //prints detailes info about each node void tree_print_debug(tree_node<T>* root, int depth=0, ostream& outs=cout); template <typename T> //clear the tree void tree_clear(tree_node<T>* &root); template <typename T> //erase target from the tree bool tree_erase(tree_node<T>*& root, const T& target); template <typename T> //erase rightmost node from the tree -> max_value void tree_remove_max(tree_node<T>* &root, T& max_value); template <typename T> //print in_order void in_order(tree_node<T>* root,ostream& outs=cout); template <typename T> //print pre_order void pre_order(tree_node<T>* root,ostream& outs=cout); template <typename T> //print post_order void post_order(tree_node<T>* root,ostream& outs=cout); template <typename T> //string in_order string in_order_string(tree_node<T>* root); template <typename T> //string pre_order string pre_order_string(tree_node<T>* root); template <typename T> //string post_order string post_order_string(tree_node<T>* root); template <typename T> //return copy of tree pointed to by root tree_node<T>* tree_copy(tree_node<T>* root); template <typename T> //Add tree src to dest void tree_add(tree_node<T>* & dest, const tree_node<T>* src); template <typename T> //sorted array of ints -> tree tree_node<T>* tree_from_sorted_list(const T* a); template <typename T> // sorted array -> tree tree_node<T>* tree_from_sorted_list(const T* a, int size);
You will write individual functions that will test every aspect of these. The insertion, the deletion, the copying and clearing and of course searching.