// ----------------------------------------------------------------------- // // Binary search tree template classes // File: BinSearchTree/bstree.h // // ----------------------------------------------------------------------- #ifndef _BSTREE_H #define _BSTREE_H #include #include "queStack.h" #include typedef unsigned int UINT; // ----------------------------------------------------------------------- // forward declarations template class BTree; template class BTreeIterator; template class PreorderIterator; template class InorderIterator; template class PostorderIterator; template class LevelIterator; // ----------------------------------------------------------------------- template class BTnode { friend class BTree; friend class BTreeIterator; friend class PreorderIterator; friend class InorderIterator; friend class PostorderIterator; friend class LevelIterator; friend ostream& operator<< (ostream&, const BTree&); T data; // all members BTnode *le; // are private BTnode *ri; // constructors BTnode () {} BTnode (const T& t, BTnode *l, BTnode *r) : data(t) { le=l; ri=r; } }; // ----------------------------------------------------------------------- template class BTree { friend class BTreeIterator; friend class PreorderIterator; friend class InorderIterator; friend class PostorderIterator; friend class LevelIterator; BTnode *LEAF; // sentinel, LEAF->ri is also the root pointer UINT size; // number of nodes UINT ht; // height of tree // ------------------------------------------------------------------ typedef BTreeIterator *iterptr; list< iterptr > iterlist; // ------------------------------------------------------------------ int depth; void doEmpty (BTnode*); // recursive aux. functions void redoHeight (BTnode*, UINT); void prePrint (BTnode*); public: BTree (); // constructor ~BTree (); // destructor T& operator[] (const BTreeIterator& it) // return "curr" element { return it.curr->data; } // pointed to by iterator void insert (const T&); // insert in sorted tree bool remove (const T&); // remove first instance bool search (const T&); bool isEmpty () { return bool(LEAF->ri==LEAF); } UINT nNodes () { return size; } UINT height () { return ht; } void makeEmpty (); void print () { prePrint(LEAF->ri); } }; // ----------------------------------------------------------------------- template // Base class for all iterator classes class BTreeIterator { friend class BTree; protected: stack_queue*> > stque; BTree *tree; BTnode *curr; public: BTreeIterator (BTree&); virtual ~BTreeIterator (); void reset (); bool atEnd () { return bool (curr==tree->LEAF); } virtual BTreeIterator& operator++ () = 0; operator== (const BTreeIterator& it) { return (curr==it.curr); } }; // ----------------------------------------------------------------------- template class PreorderIterator : public BTreeIterator { public: PreorderIterator (BTree& bt) : BTreeIterator(bt) { reset(); } BTreeIterator& operator++ (); }; // ----------------------------------------------------------------------- template class InorderIterator : public BTreeIterator { public: InorderIterator (BTree& bt) : BTreeIterator(bt) { reset(); } BTreeIterator& operator++ (); }; // ----------------------------------------------------------------------- template class PostorderIterator : public BTreeIterator { public: PostorderIterator (BTree& bt) : BTreeIterator(bt) { reset(); } BTreeIterator& operator++ (); }; // ----------------------------------------------------------------------- template class LevelIterator : public BTreeIterator { public: LevelIterator (BTree& bt) : BTreeIterator(bt) { reset(); } BTreeIterator& operator++ (); }; // ----------------------------------------------------------------------- template void BTree::doEmpty (BTnode *s) { if (s == LEAF) return; doEmpty (s->le); // recursively deletes each node doEmpty (s->ri); // in a POSTORDER traversal delete s; } // ---------------------------------------------------------------------- template void BTree::redoHeight (BTnode *s, UINT d) { if (s == LEAF) return; redoHeight (s->le, d+1); // recursively re-computes redoHeight (s->ri, d+1); // the height of the tree if (d > ht) ht = d; } // ---------------------------------------------------------------------- template // prints the tree in void BTree::prePrint (BTnode *s) // PREORDER { if (s == LEAF) return; ++depth; cout << depth << "\t" << s->data << "\t--->\t"; if (s->le == LEAF) cout << "" << "\t"; else cout << s->le->data << "\t"; if (s->ri == LEAF) cout << "" << endl; else cout << s->ri->data << endl; prePrint (s->le); prePrint (s->ri); --depth; } // ---------------------------------------------------------------------- template // constructor BTree::BTree () { LEAF = new BTnode; LEAF->le = LEAF; LEAF->ri = LEAF; // "root" pointer size = ht = 0; depth = -1; } // ---------------------------------------------------------------------- template // destructor BTree::~BTree () { doEmpty (LEAF->ri); delete LEAF; // reset iterators referring to this tree list::iterator p; for(p = iterlist.begin(); p != iterlist.end(); p++) { (*p)->curr = NULL; (*p)->tree = NULL; } } // ---------------------------------------------------------------------- template // inserts "tval" into the void BTree::insert (const T& tval) // sorted binary tree { // LEAF is used as sentinel BTnode *p = LEAF; BTnode *c = LEAF->ri; LEAF->data = tval; UINT h = 0; while (c != LEAF) { p = c; c = (tval < c->data) ? c->le : c->ri; ++h; } c = new BTnode(tval, LEAF, LEAF); assert (c); if (tval < p->data) p->le = c; else p->ri = c; // reset all iterators list::iterator it; for (it=iterlist.begin(); it!=iterlist.end(); it++) (*it)->reset (); ++size; if (h > ht) ht = h; // adjust height } // ---------------------------------------------------------------------- template // removes the first instance bool BTree::remove (const T& tval) // of "tval" { BTnode *p = LEAF; BTnode *c = LEAF->ri; LEAF->data = tval; while (tval != c->data) { p = c; c = (tval < c->data) ? c->le : c->ri; } if (c == LEAF) return false; // not found BTnode *t = c; if (t->ri == LEAF) // case #1 { c = c->le; } else if (t->ri->le == LEAF) // case #2 { c = c->ri; c->le = t->le; } else // case #3 { BTnode *q = c->ri; while (q->le->le != LEAF) q = q->le; c = q->le; q->le = c->ri; c->le = t->le; c->ri = t->ri; } if (tval < p->data) p->le = c; else p->ri = c; delete t; // reset all iterators list::iterator it; for (it=iterlist.begin(); it!=iterlist.end(); it++) (*it)->reset (); ht = 0; redoHeight (LEAF->ri, 0); --size; return true; } // ---------------------------------------------------------------------- template bool BTree::search (const T& tval) { BTnode *p = LEAF->ri; LEAF->data = tval; while (tval != p->data) p = (tval < p->data) ? p->le : p->ri; if (p == LEAF) return false; return true; } // ---------------------------------------------------------------------- template void BTree::makeEmpty () { doEmpty (LEAF->ri); // reset all iterators list::iterator p; for (p=iterlist.begin(); p!=iterlist.end(); p++) { (*p)->stque.makeEmpty(); (*p)->curr = LEAF; } size = 0; ht = 0; } // ---------------------------------------------------------------------- template BTreeIterator::BTreeIterator (BTree& t) : tree(&t) { (t.iterlist).push_front(this); } // ---------------------------------------------------------------------- template BTreeIterator::~BTreeIterator () { stque.makeEmpty (); // find iterator record list< BTree::iterptr >::iterator p = find(tree->iterlist.begin(), tree->iterlist.end(), this); tree->iterlist.erase(p); } // ---------------------------------------------------------------------- template void BTreeIterator::reset () { curr = tree->LEAF; stque.makeEmpty (); ++(*this); // operator++ (); } // ---------------------------------------------------------------------- template BTreeIterator& PreorderIterator::operator++ () { if (curr->ri != tree->LEAF) stque.push (curr->ri); if (curr->le != tree->LEAF) stque.push (curr->le); if (stque.isEmpty ()) curr = tree->LEAF; else curr = stque.pop (); return *this; } // ---------------------------------------------------------------------- template BTreeIterator& InorderIterator::operator++ () { BTnode *p = curr->ri; while (p != tree->LEAF) { stque.push (p); p=p->le; } if (stque.isEmpty ()) curr = tree->LEAF; else curr = stque.pop (); return *this; } // ---------------------------------------------------------------------- template BTreeIterator& PostorderIterator::operator++ () { BTnode *p = tree->LEAF; if (!stque.isEmpty ()) p = stque.pop (); if (p->ri!=tree->LEAF && curr!=p->ri) { stque.push (p); p = p->ri; while (p!=tree->LEAF) { stque.push (p); if (p->le!=tree->LEAF) p = p->le; else p = p->ri; } p = stque.pop (); } curr = p; return *this; } // ---------------------------------------------------------------------- template BTreeIterator& LevelIterator::operator++ () { if (curr->le != tree->LEAF) stque.append (curr->le); if (curr->ri != tree->LEAF) stque.append (curr->ri); if (stque.isEmpty ()) curr = tree->LEAF; else curr = stque.pop (); return *this; } // ---------------------------------------------------------------------- #endif