/****************************************************************** * Memorial University of Newfoundland * Engineering 4892 Data Structures * * $RCSfile: BinTree.h,v $ $Revision: 1.2 $ * $Date: 2001-07-11 11:46:57-02:30 $ * $State: Exp $ * * Binary Tree class template. * ******************************************************************/ /****************************************************************** * REVISION HISTORY * * $Log: BinTree.h,v $ * Revision 1.2 2001-07-11 11:46:57-02:30 dpeters * Added DuplicateElement to Status, checked with M$ Visual C++ * * Revision 1.1 2001-07-10 17:00:58-02:30 dpeters * Initial revision * * ******************************************************************/ #ifndef BINTREE_DEF #define BINTREE_DEF #include #include #include #include template class BinaryNode // The node of the binary tree { public: T key; BinaryNode* left; BinaryNode* right; BinaryNode(BinaryNode *l = 0, BinaryNode* r = 0) : left(l), right(r) { } BinaryNode(const T& k, BinaryNode *l = 0, BinaryNode* r = 0) : key(k), left(l), right(r) { } }; template class BinaryTree { public: // Local types enum Status { Ok, NewFail, NoSuchElement, DuplicateElement }; // Constructors BinaryTree(); // Post: empty tree constructed BinaryTree(const BinaryTree& r); // Post: tree is a copy of r // Destructor virtual ~BinaryTree(); // Accessors bool empty() const; // Post: Result = (tree is empty) int height() const; // Post: Result = length of longest path from root to a leaf Status getStatus() const { return err; } // Post: Result = status of last access std::vector preorderList() const; std::vector inorderList() const; std::vector postorderList() const; std::string toString() const; // Mutators Status insert(const T& x); // Post: x is inserted in the tree keeping it optimally balanced BinaryTree& operator=(const BinaryTree& r); // Assignment operator // Post: this is a copy of r protected: BinaryNode* root; mutable Status err; // Status of the last call. private: // Private methods BinaryNode* rCopyTree(const BinaryNode* r); void rDeleteTree(BinaryNode* r); int rTreeHeight(BinaryNode* r) const; virtual Status rInsert(BinaryNode*& r, const T& x); void rPreorderList(BinaryNode* r, std::vector& l) const; void rInorderList(BinaryNode* r, std::vector& l) const; void rPostorderList(BinaryNode* r, std::vector& l) const; void rToString(BinaryNode* r, std::ostrstream& l, int depth) const; }; #include #include /****************************************************************** * BinaryTree -- constructor * * Post: err = Ok /\ root = 0 *******************************************************************/ template BinaryTree::BinaryTree() { root = 0; err = Ok; } /****************************************************************** * BinaryTree -- copy constructor * * Post: err = Ok -> root points to a tree that is a copy of r * err = NewFail -> memory allocation failure *******************************************************************/ template BinaryTree::BinaryTree(const BinaryTree& r) { root = rCopyTree(r.root); } /****************************************************************** * ~BinaryTree -- destructor * *******************************************************************/ template BinaryTree::~BinaryTree() { rDeleteTree(root); err = Ok; } /****************************************************************** * empty -- return true if the tree is empty, false otherwise * * Post: Result = root == 0 *******************************************************************/ template bool BinaryTree::empty() const { return (root == 0); } /****************************************************************** * height -- return the height of the tree * * Post: Result = height of the tree *******************************************************************/ template int BinaryTree::height() const { return rTreeHeight(root); } /****************************************************************** * operator= -- assignment operator * * Post: err = Ok -> (this is a copy of r) * err = NewFail -> root = 0 (memory allocation failure) *******************************************************************/ template BinaryTree& BinaryTree::operator=(const BinaryTree& r) { if (&r != this) { rDeleteTree(root); err = Ok; root = rCopyTree(r.root); } return *this; } /****************************************************************** * insert -- insert an element in the tree, keeping it balanced * * Post: *******************************************************************/ template BinaryTree::Status BinaryTree::insert(const T& x) { return rInsert(root, x); } /****************************************************************** * preorderList -- construct a list in preorder form * * Post: Result = list of elements from tree in pre-order *******************************************************************/ template std::vector BinaryTree::preorderList() const { std::vector l; rPreorderList(root, l); return l; } /****************************************************************** * inorderList -- construct a list in inorder form * * Post: Result = list of elements from tree in pre-order *******************************************************************/ template std::vector BinaryTree::inorderList() const { std::vector l; rInorderList(root, l); return l; } /****************************************************************** * postorderList -- construct a list in postorder form * * Post: Result = list of elements from tree in pre-order *******************************************************************/ template std::vector BinaryTree::postorderList() const { std::vector l; rPostorderList(root, l); return l; } /****************************************************************** * toString -- produce a bracketed string representation of the tree * * Post: Result = string containing the string representation *******************************************************************/ template std::string BinaryTree::toString() const { std::ostrstream l; rToString(root, l, 0); l << '\0'; return l.str(); } template BinaryNode* BinaryTree::rCopyTree(const BinaryNode* src) { BinaryNode* result = 0; if (src != 0 && err == Ok) { result = new(std::nothrow) BinaryNode(src->key); if (result != 0) { result->left = rCopyTree(src->left); result->right = rCopyTree(src->right); } else { err = NewFail; } } return result; } template void BinaryTree::rDeleteTree(BinaryNode* cur) { if (cur != 0) { rDeleteTree(cur->left); rDeleteTree(cur->right); delete cur; } } template int BinaryTree::rTreeHeight(BinaryNode* r) const { int result = 0; if (r != 0) { result = 1 + std::max(rTreeHeight(r->left), rTreeHeight(r->right)); // You could also do this the 'old-fashioned' way: // int lh = rTreeHeight(r->left); // int rh = rTreeHeight(r->right); // if (lh > rh) { // result = 1 + lh; // } else { // result = 1 + rh; // } // (It appears that "max" is not defined in the STL implementation that // ships with M$ Visual C++, so you might need to do it the // old-fashioned way if you want to use that software.) } return result; } template BinaryTree::Status BinaryTree::rInsert(BinaryNode*& r, const T& x) { if (r == 0) { r = new(std::nothrow) BinaryNode(x); if (r != 0) { err = Ok; } else { err = NewFail; } } else if (rTreeHeight(r->left) <= rTreeHeight(r->right)) { err = rInsert(r->left, x); } else { err = rInsert(r->right, x); } return err; } template void BinaryTree::rPreorderList(BinaryNode* r, std::vector& l) const { if (r != 0) { l.push_back(r->key); rPreorderList(r->left, l); rPreorderList(r->right, l); } } template void BinaryTree::rInorderList(BinaryNode* r, std::vector& l) const { if (r != 0) { rInorderList(r->left, l); l.push_back(r->key); rInorderList(r->right, l); } } template void BinaryTree::rPostorderList(BinaryNode* r, std::vector& l) const { if (r != 0) { rPostorderList(r->left, l); rPostorderList(r->right, l); l.push_back(r->key); } } template void BinaryTree::rToString(BinaryNode* r, std::ostrstream& l, int depth) const { if (r != 0) { rToString(r->right, l, depth+1); for (int i = 0; i < depth; i++) l << "\t"; l << r->key <<"\n"; rToString(r->left, l, depth+1); } } #endif