SOURCE FILE:  BT.cpp 
// ********************************************************
// Implementation file BT.cpp for the ADT binary tree.
// ********************************************************
#include "BT.h"      // header file
#include <stddef.h>  // definition of NULL
#include <assert.h>  // for assert()
struct treeNode
{  treeItemType Item;
   ptrType      LChildPtr, RChildPtr;
   // constructor:
   treeNode(const treeItemType& NodeItem, ptrType L,
            ptrType R);
};  // end struct
treeNode::treeNode(const treeItemType& NodeItem,
                   ptrType L, ptrType R):
   Item(NodeItem), LChildPtr(L), RChildPtr(R)
{
}  // end constructor
binTreeClass::binTreeClass() : Root(NULL)
{
}  // end default constructor
binTreeClass::binTreeClass(const treeItemType& RootItem)
{
   Root = new treeNode(RootItem, NULL, NULL);
   assert(Root != NULL);
}  // end constructor
binTreeClass::binTreeClass(const treeItemType& RootItem,
                           const binTreeClass& LeftTree,
                           const binTreeClass& RightTree)
{
   bool Success;
   Root = new treeNode(RootItem, NULL, NULL);
   assert(Root != NULL);
   AttachLeftSubtree(LeftTree, Success);
   if (Success)
      AttachRightSubtree(RightTree, Success);
   assert(Success);
}  // end constructor
binTreeClass::binTreeClass(const binTreeClass& Tree)
{
   CopyTree(Tree.Root, Root);
}  // end copy constructor
binTreeClass::binTreeClass(ptrType NodePtr):
   Root(NodePtr)
{
}  // end protected constructor
binTreeClass::~binTreeClass()
{
   DestroyTree(Root);
}  // end destructor
bool binTreeClass::BinaryTreeIsEmpty() const
{
   return bool(Root == NULL);
}  // end BinaryTreeIsEmpty
treeItemType binTreeClass::RootData() const
{
   assert(Root != NULL);
   return Root->Item;
}  // end RootData
void binTreeClass::SetRootData(const treeItemType& NewItem)
{
   if (Root != NULL)
      Root->Item = NewItem;
   else
   {  Root = new treeNode(NewItem, NULL, NULL);
      assert(Root != NULL);
   }  // end if
}  // end SetRootData
void binTreeClass::AttachLeft(const treeItemType& NewItem,
                              bool& Success)
{
   Success = bool(!BinaryTreeIsEmpty() &&
                     Root->LChildPtr == NULL);
   if (Success)  // Assertion: nonempty tree; no left child
   {  Root->LChildPtr = new treeNode(NewItem, NULL, NULL);
      assert(Root->LChildPtr != NULL);
   }  // end if
}  // end AttachLeft
void binTreeClass::AttachRight(const treeItemType& NewItem,
                               bool& Success)
{
   Success = bool(!BinaryTreeIsEmpty() &&
                     Root->RChildPtr == NULL);
   if (Success)  // Assertion: nonempty tree; no right child
   {  Root->RChildPtr = new treeNode(NewItem, NULL, NULL);
      assert(Root->RChildPtr != NULL);
   }  // end if
}  // end AttachRight
void binTreeClass::AttachLeftSubtree(const binTreeClass& LeftTree,
                                     bool& Success)
{
   Success = bool(!BinaryTreeIsEmpty() &&
                     Root->LChildPtr == NULL);
   if (Success)  // Assertion: nonempty tree; no left child
      CopyTree(LeftTree.Root, Root->LChildPtr);
}  // end AttachLeftSubtree
void binTreeClass::AttachRightSubtree(const binTreeClass& RightTree,
                                      bool& Success)
{
   Success = bool(!BinaryTreeIsEmpty() &&
                     Root->RChildPtr == NULL);
   if (Success)  // Assertion: nonempty tree; no right child
      CopyTree(RightTree.Root, Root->RChildPtr);
}  // end AttachRightSubtree
void binTreeClass::DetachLeftSubtree(binTreeClass& LeftTree,
                                     bool& Success)
{
   Success = bool(!BinaryTreeIsEmpty());
   if (Success)
   {  LeftTree = binTreeClass(Root->LChildPtr);
      Root->LChildPtr = NULL;
   }  // end if
}  // end DetachLeftSubtree
void binTreeClass::DetachRightSubtree(binTreeClass& RightTree,
                                      bool& Success)
{
   Success = bool(!BinaryTreeIsEmpty());
   if (Success)
   {  RightTree = binTreeClass(Root->RChildPtr);
      Root->RChildPtr = NULL;
   }  // end if
}  // end DetachRightSubtree
binTreeClass binTreeClass::LeftSubtree() const
{
   ptrType SubTreePtr;
   if (BinaryTreeIsEmpty())
      return binTreeClass();
   else
   {  CopyTree(Root->LChildPtr, SubTreePtr);
      return binTreeClass(SubTreePtr);
   }  // end if
}  // end LeftSubtree
binTreeClass binTreeClass::RightSubtree() const
{
   ptrType SubTreePtr;
   if (BinaryTreeIsEmpty())
      return binTreeClass();
   else
   {  CopyTree(Root->RChildPtr, SubTreePtr);
      return binTreeClass(SubTreePtr);
   }  // end if
}  // end RightSubtree
void binTreeClass::PreorderTraverse(functionType Visit)
{
   Preorder(Root, Visit);
}  // end PreorderTraverse
void binTreeClass::InorderTraverse(functionType Visit)
{
   Inorder(Root, Visit);
}  // end InorderTraverse
void binTreeClass::PostorderTraverse(functionType Visit)
{
   Postorder(Root, Visit);
}  // end PostorderTraverse
binTreeClass& binTreeClass::operator=(const binTreeClass& Rhs)
{
   if (this != &Rhs)
   {  DestroyTree(Root);  // deallocate left-hand side
      CopyTree(Rhs.Root, Root);  // copy right-hand side
   }  // end if
   return *this;
}  // end operator=
void binTreeClass::CopyTree(ptrType TreePtr,
                            ptrType& NewTreePtr) const
{
   // preorder traversal
   if (TreePtr != NULL)
   {  // copy node
      NewTreePtr = new treeNode(TreePtr->Item, NULL, NULL);
      assert(NewTreePtr != NULL);
      CopyTree(TreePtr->LChildPtr, NewTreePtr->LChildPtr);
      CopyTree(TreePtr->RChildPtr, NewTreePtr->RChildPtr);
   }  // end if
   else
      NewTreePtr = NULL;  // copy empty tree
}  // end CopyTree
void binTreeClass::DestroyTree(ptrType& TreePtr)
{
   // postorder traversal
   if (TreePtr != NULL)
   {  DestroyTree(TreePtr->LChildPtr);
      DestroyTree(TreePtr->RChildPtr);
      delete TreePtr;
      TreePtr = NULL;
   }  // end if
}  // end DestroyTree
ptrType binTreeClass::RootPtr() const
{
   return Root;
}  // end RootPtr
void binTreeClass::SetRootPtr(ptrType NewRoot)
{
   Root = NewRoot;
}  // end SetRoot
void binTreeClass::GetChildPtrs(ptrType NodePtr, ptrType& LeftPtr,
                                ptrType& RightPtr) const
{
   LeftPtr = NodePtr->LChildPtr;
   RightPtr = NodePtr->RChildPtr;
}  // end GetChildPtrs
void binTreeClass::SetChildPtrs(ptrType NodePtr, ptrType LeftPtr,
                                ptrType RightPtr)
{
   NodePtr->LChildPtr = LeftPtr;
   NodePtr->RChildPtr = RightPtr;
}  // end SetChildPtrs
void binTreeClass::Preorder(ptrType TreePtr,
                            functionType Visit)
{
   if (TreePtr != NULL)
   {  Visit(TreePtr->Item);
      Preorder(TreePtr->LChildPtr, Visit);
      Preorder(TreePtr->RChildPtr, Visit);
   } // end if
}  // end Preorder
void binTreeClass::Inorder(ptrType TreePtr,
                           functionType Visit)
{
   if (TreePtr != NULL)
   {  Inorder(TreePtr->LChildPtr, Visit);
      Visit(TreePtr->Item);
      Inorder(TreePtr->RChildPtr, Visit);
   } // end if
}  // end Inorder
void binTreeClass::Postorder(ptrType TreePtr,
                             functionType Visit)
{
   if (TreePtr != NULL)
   {  Postorder(TreePtr->LChildPtr, Visit);
      Postorder(TreePtr->RChildPtr, Visit);
      Visit(TreePtr->Item);
   } // end if
}  // end Postorder
// End of implementation file.