Please send questions to st10@humboldt.edu .
/************************************************************/
/* implementation of .h file from                           *
/* http://www.cs.colorado.edu/~main/chapter10/bt_class.h    */
/*                                                          */
/* Main and Savitch, "Data Structures and Other Objects     */
/*    using C++", 2nd edition, Addison-Wesley, Ch.10        */
/************************************************************/

//-----------------------------------------------------------
// File: binary_tree.template
// Name: Sharon Tuttle
//       (implementing a .h file adapted from
//       Savitch and Main)
// last modified: 3-31-05
//
// Template Class: binary_tree<Item> (a binary tree where each
//                 node contains an Item)
//    See binary_tree.h for documentation.
//
// Because this is a template class, it is included in
//    the header file, and not compiled separately.
//
// INVARIANT for the binary_tree class:
//   1. The items in the binary tree are stored in a linked
//      structure, within nodes that have links to their left
//      and right children. The root node is pointed to by
//      the pointer root_ptr.
//   2. Each non-empty binary_tree instance always has a
//      "current_node" --- the pointer current_ptr points to
//      this node.
//--------------------------------------------------------------

#include <cassert>             // Provides assert
#include "binary_tree_node.h"  // Node template class
using namespace std;

/********************************************************/
/* CONSTRUCTORS and DESTRUCTOR                          */
/********************************************************/

// constructor 
//
template <typename Item>
binary_tree<Item>::binary_tree( )
{
    root_ptr = NULL;
    current_ptr = NULL;
}

// copy constructor
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
binary_tree<Item>::binary_tree(const binary_tree<Item>& source) 
{
    root_ptr = tree_copy(source.root_ptr);

    // where should current_ptr for new copy point?
    //    If copied an empty tree, current_ptr is NULL;
    //    otherwise, we'll start it at the root, I think.
    if (root_ptr == NULL)
    {
        current_ptr = NULL;
    }
    else
    {
        current_ptr = root_ptr;
    }
}

// destructor
//
// Library facilities used: binary_tree_node.h
template <typename Item>
binary_tree<Item>::~binary_tree()
{
    tree_clear(root_ptr);
}

        
/*************************************************************/
/* ACCESSORS and other constant member functions (observers) */
/*************************************************************/

// postcondition: returns the number of nodes in the 
//    binary_tree.
//
// Library facilities used: binary_tree_node.h 
//
template <typename Item>
size_t binary_tree<Item>::get_size( ) const
{
    return tree_size(root_ptr);
}

// postcondition: returns true if the binary_tree is 
//    empty, returns false otherwise.
//
template <typename Item>
bool binary_tree<Item>::is_empty( ) const
{
    return (root_ptr == NULL);
}
        
// retrieve
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
Item binary_tree<Item>::retrieve( ) const
{
    assert(get_size( ) > 0);

    return current_ptr->get_data( );
}

// is_root
//
template <typename Item>
bool binary_tree<Item>::is_root( ) const
{
    return( (get_size( ) > 0) && (current_ptr == root_ptr) );
}

// is_leaf
//
template <typename Item>
bool binary_tree<Item>::is_leaf( ) const
{
    return( (get_size( ) > 0) &&
            (! has_left_child( ) ) &&
            (! has_right_child( ) ) );
}

// has_parent
//
template <typename Item>
bool binary_tree<Item>::has_parent( ) const
{
    return ( (get_size( ) > 0) &&
             // if current isn't root, it must have a parent!
             (current_ptr != root_ptr) );
}

// has_left_child
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
bool binary_tree<Item>::has_left_child( ) const
{
    return ( (get_size( ) > 0) &&
             (current_ptr->get_left( ) != NULL ) );
}

// has_right_child
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
bool binary_tree<Item>::has_right_child( ) const
{
    return ( (get_size( ) > 0) &&
             (current_ptr->get_right( ) != NULL ) );
}

/****************************************************/
/* MODIFIERS and other modifying member functions   */
/****************************************************/

// create_root
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::create_root(const Item& entry)
{
    assert( get_size( ) == 0 );

    root_ptr = new binary_tree_node<Item>(entry);
    current_ptr = root_ptr;
}
 
// add_left
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::add_left(const Item& entry)
{
    assert( get_size( ) > 0 );
    assert( has_left_child( ) == false );

    binary_tree_node<Item> *new_left_ptr;

    new_left_ptr = new binary_tree_node<Item>(entry);
    current_ptr->set_left(new_left_ptr);
}

// add_right
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::add_right(const Item& entry)
{
    assert( get_size( ) > 0 );
    assert( has_right_child( ) == false );

    binary_tree_node<Item> *new_right_ptr;

    new_right_ptr = new binary_tree_node<Item>(entry);
    current_ptr->set_right(new_right_ptr);
}

// add_left_subtree
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::add_left_subtree(binary_tree<Item>& left_subtree)
{
    assert( get_size( ) > 0 );
    assert( has_left_child( ) == false );

    current_ptr->set_left(left_subtree.root_ptr);
}

// add_right_subtree
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::add_right_subtree(
    binary_tree<Item>& right_subtree)
{
    assert( get_size( ) > 0 );
    assert( has_right_child( ) == false );

    current_ptr->set_right(right_subtree.root_ptr);
}

// change
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::change(const Item& entry)
{
    assert( get_size( ) > 0 );

    current_ptr->set_data(entry);
}

// remove_left_subtree
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::remove_left_subtree( )
{
    assert( get_size( ) > 0 );
    assert( has_left_child( ) == true );

    tree_clear( current_ptr->get_left( ) );
}

// remove_right_subtree
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::remove_right_subtree( )
{
    assert( get_size( ) > 0 );
    assert( has_right_child( ) == true );

    tree_clear( current_ptr->get_right( ) );
}

// clear_tree
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::clear_tree( )
{
    tree_clear( root_ptr );
    current_ptr = NULL;
}

// shift_to_root
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::shift_to_root( )
{
    assert( get_size( ) > 0 );

    current_ptr = root_ptr;
}

// shift_left
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::shift_left( )
{
    assert( has_left_child( ) == true );

    current_ptr = current_ptr->get_left( );
}

// shift_right
//
// Library facilities used: binary_tree_node.h
//
template <typename Item>
void binary_tree<Item>::shift_right( )
{
    assert( has_right_child( ) == true );

    current_ptr = current_ptr->get_right( );
}

// print_tree
//
template <typename Item>
void binary_tree<Item>::print_tree(size_t depth)
{
    print(root_ptr, depth);
}

/****************************************************/
/* OVERLOADED OPERATORS                             */
/****************************************************/

// =
//
// Library facilities used: binary_tree_node.h
template <typename Item>
void binary_tree<Item>::operator =(const binary_tree<Item>& source) 
{
    if (this == &source) // Handle self-assignment
        return;

    tree_clear(root_ptr);
    root_ptr = tree_copy(source.root_ptr);

    // where should current_ptr for new copy point?
    //    If copied an empty tree, current_ptr is NULL;
    //    otherwise, we'll start it at the root, I think.
    if (root_ptr == NULL)
    {
        current_ptr = NULL;
    }
    else
    {
        current_ptr = root_ptr;
    }
}