/* * Default Constructor: creates an empty tree */ template BinaryTree::BinaryTree() : sz(1) { rt = new Node; } /* * Copy Constructor */ template BinaryTree::BinaryTree(const BinaryTree& orig) { sz = orig.sz; rt = cloneRecurse(orig,orig.rt); } /* * Overloaded Assignment Operator */ template BinaryTree& BinaryTree::operator=(const BinaryTree& orig) { if (this != &orig) { clearRecurse(rt); rt = cloneRecurse(orig,orig.rt); } return *this; } /* * Destructor */ template BinaryTree::~BinaryTree() { clearRecurse(rt); } /****************************** query methods ****************************/ /* * returns size of tree */ template int BinaryTree::size() const { return sz; } /* * does position correspond to internal node? */ template bool BinaryTree::isInternal(const Position& p) const throw(InvalidPositionException) { NodePtr v = p.validate(this); return v->left != NULL; } /* * does position correspond to external node? */ template bool BinaryTree::isExternal(const Position& p) const throw(InvalidPositionException) { NodePtr v = p.validate(this); return v->left == NULL; } /* * is this the root position? */ template bool BinaryTree::isRoot(const Position& p) const throw(InvalidPositionException) { NodePtr v = p.validate(this); return v == rt; } /****************************** accessor methods ****************************/ /* * return position of root of tree */ template typename BinaryTree::Position BinaryTree::root() const { return Position(this,rt); } /* * return position of parent of given position */ template typename BinaryTree::Position BinaryTree::parent(const Position& p) const throw(BoundaryViolationException, InvalidPositionException) { NodePtr v = p.validate(this); if (v==rt) throw BoundaryViolationException("Cannot traverse parent of root"); return Position(this,v->parent); } /* * return position of left child of given position */ template typename BinaryTree::Position BinaryTree::leftChild(const Position& p) const throw(BoundaryViolationException, InvalidPositionException) { NodePtr v = p.validate(this); if (v->left==NULL) throw BoundaryViolationException("Cannot traverse child of external position"); return Position(this,v->left); } /* * return position of right child of given position */ template typename BinaryTree::Position BinaryTree::rightChild(const Position& p) const throw(BoundaryViolationException, InvalidPositionException) { NodePtr v = p.validate(this); if (v->right==NULL) throw BoundaryViolationException("Cannot traverse child of external position"); return Position(this,v->right); } /* * return position of sibling of given position */ template typename BinaryTree::Position BinaryTree::sibling(const Position& p) const throw(BoundaryViolationException, InvalidPositionException) { NodePtr v = p.validate(this); if (v==rt) throw BoundaryViolationException("Cannot traverse sibling of root"); NodePtr parent = v->parent; NodePtr lc = parent->left; NodePtr s = (v==lc ? parent->right : lc); return Position(this,s); } /* * return iterator of all children of given position */ template typename BinaryTree::PositionalIterator BinaryTree::children(const Position& p) const throw(InvalidPositionException) { NodePtr v = p.validate(this); PositionalIterator PI; if (v->left!=NULL) { PI.items.push_back(Position(this,v->left)); PI.items.push_back(Position(this,v->right)); } return PI; } /* * return iterator of all children of given position */ template typename BinaryTree::PositionalIterator BinaryTree::positions() const { PositionalIterator PI; recurseAdd(PI,rt); return PI; } template void BinaryTree::recurseAdd(PositionalIterator &pi, const NodePtr v) const { if (v->left!=NULL) recurseAdd(pi,v->left); pi.items.push_back(Position(this,v)); if (v->right!=NULL) recurseAdd(pi,v->right); } /* * return iterator of all elements stored in the tree */ template typename BinaryTree::ObjectIterator BinaryTree::elements() const { ObjectIterator OI; recurseAdd(OI,rt); return OI; } template void BinaryTree::recurseAdd(ObjectIterator &oi, const NodePtr v) const { if (v->left!=NULL) recurseAdd(oi,v->left); oi.items.push_back(v->element); if (v->right!=NULL) recurseAdd(oi,v->right); } /* * replace the element at the given position */ template void BinaryTree::replaceElement(const Position& p, const Object& element) throw(InvalidPositionException) { NodePtr v = p.validate(this); v->element = element; } /* * swap the elements stored at the given positions */ template void BinaryTree::swapElements(const Position& p, const Position& q) throw(InvalidPositionException) { NodePtr v = p.validate(this); NodePtr w = q.validate(this); Object e = v->element; v->element = w->element; w->element = e; } /* * Converts external position into an internal node with two newly * created external children (each of which have default element) */ template void BinaryTree::expandExternal(const Position& p) throw(InvalidPositionException, BoundaryViolationException) { NodePtr v = p.validate(this); if (v->left==NULL) { v->left = new Node(Object(),v,NULL,NULL); v->right = new Node(Object(),v,NULL,NULL); sz+=2; } else { throw BoundaryViolationException("Cannot expand internal node"); } } /* * Replaces the external position p with a subtree which mirrors the * contents of a second tree T2. * * Note well: the external node as well as the second tree itself are * destroyed as a side effect. */ template void BinaryTree::replaceExternalWithSubtree(const Position& p, BinaryTree& T2) throw(InvalidPositionException, BoundaryViolationException) { NodePtr v = p.validate(this); if (v->left==NULL) { sz+=T2.sz-1; if (v==rt) { rt = T2.rt; } else { NodePtr parent = v->parent; T2.rt->parent = parent; if (v==parent->left) parent->left = T2.rt; else parent->right = T2.rt; } // deallocate original external node delete v; // convert T2 back to a default tree (in a way so that its // original nodes are not destroyed, as they are now part of // this tree) T2.sz = 1; T2.rt = new Node; } else { throw BoundaryViolationException("Cannot replace internal node"); } } /* * Takes an external position w of tree, deletes w and the parent of * w from the tree, promoting the sibling of w into the parent's * place (see Figure 6.13) */ template typename BinaryTree::Position BinaryTree::removeAboveExternal(const Position& w) throw(InvalidPositionException, BoundaryViolationException) { NodePtr v = w.validate(this); if (v==rt) throw BoundaryViolationException("Cannot use replaceAboveExternal on root"); if (v->left!=NULL) throw BoundaryViolationException("Cannot use replaceAboveExternal on internal node"); NodePtr parent = v->parent; NodePtr grand = parent->parent; NodePtr s = sibling(w).node; if (parent==grand->left) grand->left = s; else grand->right = s; s->parent = grand; sz-=2; v->parent = parent->parent = NULL; delete parent; delete v; return Position(this,s); } /* * clears existing tree */ template void BinaryTree::clearRecurse(const NodePtr v) { if (v!=NULL) { if (v->left!=NULL) { clearRecurse(v->left); clearRecurse(v->right); } delete v; } } /* * clones an existing tree */ template typename BinaryTree::NodePtr BinaryTree::cloneRecurse(const BinaryTree& orig, const NodePtr v) { NodePtr n = new Node(v->element); if (v->left!=NULL) { n->left = cloneRecurse(orig,v->left); n->left->parent = n; n->right = cloneRecurse(orig,v->right); n->right->parent = n; } return n; } /******************************************************* * Position methods *******************************************************/ /** * utility to convert Position to node pointer */ template typename BinaryTree::NodePtr BinaryTree::Position::validate(const BinaryTree* tree) const throw(InvalidPositionException) { if (node == NULL) throw InvalidPositionException("Cannot use a NULL position"); if (container != tree) throw InvalidPositionException("Position does not below to this tree."); if (node!=tree->rt && node->parent==NULL) throw InvalidPositionException("Position appears to involve an item which has since been removed from the tree."); else return node; } /******************************************************* * Iterator methods *******************************************************/ template template BinaryTree::Iterator::Iterator() : index(0) { }; template template bool BinaryTree::Iterator::hasNext() { return (index < items.size()); } template template T BinaryTree::Iterator::next() { return items[index++]; }