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

//-----------------------------------------------------------
// FILE: binary_tree_node.h 
// Name: Michael Main, Walter Savitch
//       (adapted by Sharon M. Tuttle)
// last modified: 3-31-05
//
// Template Class: binary_tree_node<Item> (a template class 
//    for a node in a binary tree and functions for 
//    manipulating binary trees. The template parameter
//    is the type of data in each node. 
//
// Note from Main and/or Savitch:
// ------------------------------
// NOTE: I have changed the return values from the non-const 
// versions of the get_left() and get_right() functions so that they 
// return a reference to the pointer in the node. This is 
// indicated by the & symbol here:
//   binary_tree_node*& get_left( )
// The use of a "reference" in the return value has two 
// advantages that simplify the material of Chapter 10:
// 1. It now allows a direct assignment such as: 
//    p->get_left() = NULL.
//    This is not a huge advantage since the same thing can 
//    be accomplished by using the set_left function. 
// 2. The expression p->get_left() can be passed as the argument
//    to a function such as: tree_clear(p->get_left());
//    The parameter of tree_clear is a reference parameter, 
//    so that any changes that tree_clear makes to p->get_left() 
//    will now effect the actual left pointer in the node *p. 
//    In this example, the tree_clear function does set its 
//    parameter to NULL, so that the total effect of 
//    tree_clear(p->get_left()) is to clear the left
//    subtree of p and to set p's left pointer to NULL.
//    In the case of tree_clear, this is not a huge advantage 
//    because we could have just set p's left pointer to NULL 
//    ourselves. But, in Section 10.5, there are two functions, 
//    bst_remove and bst_remove_max, which are easier to write 
//    if we can use p->get_left() and p->get_right() as the parameters 
//    of recursive calls. See the partial implementation
//    of bag6.template for details:
//    http://www.cs.colorado.edu/~main/projects/chap10a.html
// -----------------------------------------------------------

#ifndef BINARY_TREE_NODE_H
#define BINARY_TREE_NODE_H

#include <cstdlib>            // provides NULL and size_t
using namespace std;

template <typename Item>
class binary_tree_node
{
    public:

        /******************************************************/
        /* TYPEDEFS and MEMBER CONSTANTS for the binary tree  */
        /*    class                                           */
        /******************************************************/

        // Each node of the tree contains a piece of data and 
        //    pointers to its children. The type of the data 
        //    (binary_tree_node<Item>::value_type) is
        //    the Item type from the template parameter. 
        // The type may be any of the C++ built-in types (int, 
        //    char, etc.), or a class with a default constructor, 
        //    and an assignment operator.
        //
        typedef Item value_type;

        /****************************************************/
        /* CONSTRUCTOR                                      */
        /****************************************************/

        // postcondition: creates a new node with data equal
        //    to init_data, and its child pointers equal to
        //    init_left and init_right.   
        //
        binary_tree_node(const Item& init_data = Item( ),
                         binary_tree_node* init_left = NULL,
                         binary_tree_node* init_right = NULL);

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

        // postcondition: returns a reference to the data from 
        //    this binary_tree_node
        //
        const Item& get_data( ) const;
        
        // postcondition: returns a pointer to the left child
        //    (which will be NULL if there is no child)
        //
        const binary_tree_node* get_left( ) const;
        
        // postcondition: returns a pointer to the right child
        //    (which will be NULL if there is no child)
        //
        const binary_tree_node* get_right( ) const;

        // WHY are these slightly-different versions here,
        //    also?! BECAUSE, as mentioned in an earlier chapter,
	//    we need one version when we are permitted to change
	//    a node, and another versons for when we are not
	//    permitted to change a node (p. 464, p. 306, p. 304)
        Item& get_data( );

        binary_tree_node*& get_left( );

        binary_tree_node*& get_right( );
        
        // postcondition: returns true if the node is a leaf;
        //    otherwise returns false.
        //
        bool is_leaf( ) const;
        
        /****************************************************/
        /* MODIFIERS and other modifying member functions   */
        /****************************************************/

        // postcondition: the binary_tree_node now contains
        //    the specified new data.
        //
        void set_data(const Item& new_data);
        
        // postcondition: the binary_tree_node now contains
        //    the specified new link to a left child.
        //
        void set_left(binary_tree_node* new_left);

        // postcondition: the binary_tree_node now contains
        //    the specified new link to a right child.
        //
        void set_right(binary_tree_node* new_right); 

    private:
        Item              data_field;
        binary_tree_node *left_field;
        binary_tree_node *right_field;
};

//--------------------------------------------------------
// NON-MEMBER FUNCTIONS for the binary_tree_node<Item>:
//-------------------------------------------------------    

// preconditions: node_ptr is a pointer to a node in a
//    binary tree (or node_ptr may be NULL to indicate the
//    empty tree). If the pointer is not NULL, then depth 
//    is the depth of the node pointed to by node_ptr.
// postconditions: If node_ptr is non-NULL, then the contents
//    of *node_ptr and all of its descendants have been 
//    written to cout with the << operator, using a 
//    backward in-order traversal. Each node is indented
//    four times its depth.
//
template <typename Item, typename SizeType>
void print(const binary_tree_node<Item>* node_ptr, SizeType depth);

// preconditions: root_ptr is the root pointer of a binary tree
//    (which may be NULL for the empty tree)
// postconditions: all nodes at the root or below have been
//    returned to the heap, and root_ptr has been set to NULL.
//
template <typename Item>
void tree_clear(binary_tree_node<Item>*& root_ptr);

// preconditions: root_ptr is the root of a binary tree (which
//    may be NULL for the empty tree).
// postconditions: a copy of the binary tree has been made, 
//    and the return value is a pointer to the root of this
//    copy.
//
template <typename Item>
binary_tree_node<Item>* tree_copy(
    const binary_tree_node<Item>* root_ptr);

// preconditions: node_ptr is a pointer to a node in a binary
//    tree (or node_ptr may be NULL to indicate the empty tree).
// postconditions: returns the number of nodes in the tree.
//
template <typename Item>
size_t tree_size(const binary_tree_node<Item>* node_ptr);

#include "binary_tree_node.template"
#endif