//----------------------------------------------------------------------
//  IMPLEMENTATION FILE (chartree.cpp)
//  This module exports 1) CharTree, an ADT for an unbounded
//  binary tree whose nodes contain char values, 2) a pointer type
//  NodePtr for accessing nodes in a tree, and 3) operations on
//  tree nodes.
//----------------------------------------------------------------------
#include "chartree.h"
#include <stddef.h>      // For NULL

struct TreeNode {
    char    data;                        // Data member
    NodePtr lLink;                       // Pointer to left child
    NodePtr rLink;                       // Pointer to right child
    TreeNode( char, NodePtr, NodePtr );  // Constructor
};

TreeNode::TreeNode( /* in */ char    someChar,
                    /* in */ NodePtr leftPtr,
                    /* in */ NodePtr rightPtr )
    //..................................................................
    // POST: data == someChar  &&  lLink == leftPtr  &&  rLink == rightPtr
    //..................................................................
{
    data = someChar;  lLink = leftPtr;  rLink = rightPtr;
}

// Private members of CharTree class:
//    NodePtr rootPtr;               Pointer to root node

CharTree::CharTree()
    //..................................................................
    // POST: rootPtr == NULL
    //..................................................................
{
    rootPtr = NULL;
}

Boolean CharTree::IsEmpty() const
    //..................................................................
    // POST: FCTVAL == (rootPtr == NULL)
    //..................................................................
{
    return (rootPtr == NULL);
}

void CharTree::BuildRoot( /* in */ char someChar )
    //..................................................................
    // PRE:  rootPtr == NULL
    // POST: rootPtr points to newly allocated node, call it N
    //    && N.data == someChar  &&  N.lLink == NULL  &&  N.rLink == NULL
    //..................................................................
{
    rootPtr = new TreeNode(someChar, NULL, NULL);
}

NodePtr CharTree::Root() const
    //..................................................................
    // POST: FCTVAL == rootPtr
    //..................................................................
{
    return rootPtr;
}

void AppendLeft( /* in */ NodePtr ptr,
                 /* in */ char    someChar )
    //..................................................................
    // PRE:  ptr != NULL  &&  Assigned(someChar)
    // POST: ptr->lLink points to newly allocated node, call it LC
    //    && LC.data == someChar  &&  LC.lLink == NULL  &&  LC.rLink == NULL
    //..................................................................
{
    ptr->lLink = new TreeNode(someChar, NULL, NULL);
}

void AppendRight( /* in */ NodePtr ptr,
                  /* in */ char    someChar )
    //..................................................................
    // PRE:  ptr != NULL  &&  Assigned(someChar)
    // POST: ptr->rLink points to newly allocated node, call it RC
    //    && RC.data == someChar  &&  RC.lLink == NULL  &&  RC.rLink == NULL
    //..................................................................
{
    ptr->rLink = new TreeNode(someChar, NULL, NULL);
}

char Data( /* in */ NodePtr ptr )
    //..................................................................
    // PRE:  ptr != NULL  &&  Assigned(ptr->data)
    // POST: FCTVAL == ptr->data
    //..................................................................
{
    return ptr->data;
}

void Store( /* in */ NodePtr ptr,
            /* in */ char    someChar )
    //..................................................................
    // PRE:  ptr != NULL  &&  Assigned(someChar)
    // POST: ptr->data == someChar
    //..................................................................
{
    ptr->data = someChar;
}

NodePtr LChild( /* in */ NodePtr ptr )
    //..................................................................
    // PRE:  Assigned(ptr)
    //    && (ptr != NULL) --> Assigned(ptr->lLink)
    // POST: FCTVAL == NULL, if ptr == NULL
    //              == ptr->lLink, otherwise
    //..................................................................
{
    return (ptr==NULL) ? NULL : ptr->lLink;
}

NodePtr RChild( /* in */ NodePtr ptr )
    //..................................................................
    // PRE:  Assigned(ptr)
    //    && (ptr != NULL) --> Assigned(ptr->rLink)
    // POST: FCTVAL == NULL, if ptr == NULL
    //              == ptr->rLink, otherwise
    //..................................................................
{
    return (ptr==NULL) ? NULL : ptr->rLink;
}

Boolean IsLeaf( /* in */ NodePtr ptr )
    //..................................................................
    // PRE:  ptr != NULL
    // POST: FCTVAL == (ptr->lLink == NULL  &&  ptr->rLink == NULL)
    //..................................................................
{
    return (ptr->lLink == NULL && ptr->rLink == NULL);
}

void DeleteLeaf( /* inout */ NodePtr& ptr )
    //..................................................................
    // PRE:  Assigned(ptr)
    // POST: *ptr deallocated
    //..................................................................
{
    delete ptr;
}


