SOURCE FILE: BT.cpp


// ********************************************************
// Implementation file BT.cpp for the ADT binary tree.

/* This is the code that came with the 2nd edition of Carrano.  So far, it
   has been tested with the g++ compiler on the CS Department Suns, but not
   the ng++ compiler.  */

// ********************************************************
#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.