Please send questions to st10@humboldt.edu .
/************************************************************/
/* ADAPTED 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, Ch.11 */
/************************************************************/

//-----------------------------------------------------------
// File: complete_tree.h
// Name: Michael Main, Walter Savitch
//       (adapted by Sharon M. Tuttle)
// last modified: 4-13-05
//
// Template Class: complete_tree<Item> (a COMPLETE binary tree 
//                 where each node contains an Item)
//
//                 Note that each non-empty complete_tree instance
//                 always has a "current node". The location of
//                 the current node is controlled by five
//                 member functions: shift_up, shift_to_root,
//                 shift_left, and shift_right, and 
//                 shift_to_lowest_right
//
// VALUE SEMANTICS for the complete_tree<Item> template class:
//    Assignments and the copy constructor may be used 
//       with complete_tree<Item> objects.
//
// DYNAMIC MEMORY USAGE by the complete_tree<Item> template class:
//    If there is insufficient dynamic memory, then the
//       following functions throw bad_alloc:
//       create_root, add_left, add_right, the copy constructor,
//       and the assignment operator.
//-----------------------------------------------------------

#ifndef COMPLETE_TREE_H
#define COMPLETE_TREE_H

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

template <typename Item>
class complete_tree
{
    public:

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

        // The template parameter, Item, is the data type of the 
        //    items in the nodes of the complete_tree, also 
        //    defined as complete_tree<Item>::value_type.
        // It may be any of the C++ built-in types (int, char, 
        //    etc.), or a class with a default constructor, a 
        //    copy constructor, and an assignment operator. 
        //
        typedef Item value_type;

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

        // postcondition: creates an empty complete tree instance
        //    (with no nodes).
        //
        complete_tree( );

        // copy constructor
        //
        complete_tree(const complete_tree<Item>& source);

        // destructor
        //
        ~complete_tree();

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

        // postcondition: returns the number of nodes in the 
        //    complete_tree.
        //
        size_t get_size( ) const;

        // postcondition: returns true if the complete_tree is 
        //    empty, returns false otherwise.
        //
        bool is_empty( ) const;

        // precondition: size( ) > 0
        // postcondition: returns (non-destructively) the data 
        //    from the "current node", BUT the complete_tree is
        //    unchanged.
        //
        Item retrieve( ) const;

        // postcondition: returns true if size( ) > 0 and 
        //    and the "current node" is the root.
        //
        bool is_root( ) const;

        // postcondition: returns true if size( ) > 0 and
        //    the "current node" is a leaf (has no children)
        //
        bool is_leaf( ) const;

        // postcondition: returns true if size( ) > 0 and
        //    the "current node" has a parent.
        //
        bool has_parent( ) const;

        // postcondition: returns true if size( ) > 0 and
        //    the "current node" has a left child.
        //
        bool has_left_child( ) const;

        // postcondition: returns true if size( ) > 0 and
        //    the "current node" has a right child.
        //
        bool has_right_child( ) const;

        // precondition: has_parent( ) == true
        // postcondition: returns the value of "current 
        //    node"'s parent
        //
        Item get_parent_value( ) const;

        // precondition: has_left_child( ) == true
        // postcondition: returns the value of the
        //    "current node"'s left child
        //
        Item get_left_value( ) const;

        // precondition: has_right_child( ) == true
        // postcondition: returns the value of the
        //    "current node"'s right child
        //
        Item get_right_value( ) const;

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

        // postconditions: a node has been added to the proper
        //    (next moving right) position at the lowest level 
        //    to maintain this as a complete binary tree, with
        //    the given entry as its value.
        //       IF the tree was EMPTY before, then current node
        //    is now the root. Otherwise, current node
        //    is unchanged.
        //
        void add(const Item& entry);

        // preconditions: size( ) > 0
        // postconditions: the rightmost node on the lowest level
        //    of the tree has been removed, and its value is
        //    returned.
        //       IF the tree is now empty, then there is no longer
        //    a "current node"
        //       IF "current node" WAS the node to be removed, then
        //    "current node" is now that removed node's parent.
        //       OTHERWISE, "current_node" is unchanged.
        //
        Item remove( );

        // precondition: size( ) > 0
        // postcondition: the data at the "current node" has
        //    been changed to the new entry
        //
        void change(const Item& entry);
 
        // postconditions: the tree is empty (and so there is
        //    no "current node")
        //
	void clear_tree( ); 

        // precondition: size( ) > 0
        // postcondition: the "current node" is now the root
        //    of the tree.
        //
        void shift_to_root( );

        // precondition: has_parent( ) == true
        // postcondition: the "current node" has been shifted
        //    up to the parent of the old current node.
        //
        void shift_up( );
    
        // precondition: has_left_child( ) == true
        // postcondition: the "current node" has been shifted
        //    down to the left child of the old current node.
        //
        void shift_left( );

        // precondition: has_right_child( ) == true
        // postcondition: the "current node" has been shifted
        //    down to the right child of the old current node.
        //
        void shift_right( );

        // precondition: size( ) != 0
        // postcondition: the "current node" has been shifted
        //    down to the rightmost item on the lowest level
        //
        void shift_to_lowest_right( );

        // preconditions: if !empty( ), depth is the depth of the 
        //    calling complete_tree instance. 
        // postconditions: if  !empty, then the contents of the 
        //    root 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.
        //
        void print_tree(size_t depth);

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

        // postcondition: the complete_tree that activated this 
        //    will be made to have the same items as source
        //
        void operator =(const complete_tree<Item>& source);

    private:
        Item   *nodes;        // array of complete tree nodes
        size_t capacity;      // current capacity of the 
                              //    complete tree
        size_t used;          // current number of items in the 
                              //    complete tree
        size_t current_index; // index of current node in tree

        // helper function: 
        //    get_parent_index
        //
        // precondition:  has_parent( ) == true
        // postcondition: returns index of current node's
        //    parent
        //
        size_t get_parent_index( ) const;

        // helper function: 
        //    get_left_index
        //
        // postcondition: returns what WOULD be index of 
        //    current node's left child (BUT it may not
        //    currently exist!)
        //
        size_t get_left_index( ) const;

        // helper function: 
        //    get_right_index
        //
        // postcondition: returns what WOULD be index of 
        //    current node's right child (BUT it may not
        //    currently exist!)
        //
        size_t get_right_index( ) const;

        // helper function:
        //    print
        // 
        // used to help accomplish print_tree
        //
        void print(size_t index, size_t depth);        
};

#include "complete_tree.template" // Include the implementation 
#endif