// BiTree.cpp // CSC 601 - Fall 2002 - Kirby // ------------------------------------------------------------------- // A binary search tree template, with an inorder traversing iterator. // Used to illustrate "STL interoperability." // From the lecture 10/22. // // QUESTION FOR DISCUSSION: // What about operator->() for the iterator? // ------------------------------------------------------------------- #pragma warning (disable:4786) // for forlorn VC++6 users #include #include using namespace std ; // Forward declaration. template< typename TCmp> class BiTreeIterator ; template< typename TCmp > class BiTree // Binary tree of TCmp objects. { friend class BiTreeIterator ; public: // Types to expose. typedef TCmp value_type ; typedef TCmp* pointer ; typedef TCmp& reference ; typedef BiTreeIterator const_iterator ; typedef int size_type ; // Life. BiTree() : _root(NULL), _size(0) {} // (a few other ctors would be appropriate too) ~BiTree() { delete _root ; } // Mutators. void insert( const TCmp& val ) ; // Inspectors. size_type size() const { return _size ; } bool isPresent( const TCmp& val ) const { return _findNode( val, _root ) != NULL ; } const_iterator begin() const ; const_iterator end() const ; private: struct Node { Node( const TCmp& val ) : val(val), left(NULL), right(NULL) {} ~Node() { delete left ; delete right ; } TCmp val ; Node *left, *right ; } ; Node* _root ; size_type _size ; static Node const * const & _findNode( const TCmp& val, Node const * const & p ) ; } ; template< typename TCmp> class BiTreeIterator : public iterator< forward_iterator_tag, TCmp > { // Const iterator for binary trees. typedef BiTree::Node Node ; // a convenient abbreviation only public: BiTreeIterator( const Node* root ) { _pushLeftmosts( root ) ; } BiTreeIterator( const BiTreeIterator& ) { /* ... */ } bool operator==( const BiTreeIterator& it ) { return _stk == it._stk ; } bool operator!=( const BiTreeIterator& it ) { return _stk != it._stk ; } const TCmp& operator*() const { return _stk.top()->val ; } BiTreeIterator& operator=( const BiTreeIterator& it ) { /* ... */ } const BiTreeIterator& operator++() ; // prefix BiTreeIterator operator++( int ) ; // postfix private: stack< const Node* > _stk ; // stores the state of an inorder traversal void _pushLeftmosts( const Node* p ) ; } ; // // BiTree methods // template< typename TCmp> inline void BiTree::insert( const TCmp& val ) // Insert val into this binary tree. { Node*& p= const_cast( _findNode( val, _root ) ) ; if ( p == NULL ) { _size++ ; p= new Node( val ) ; } } template< typename TCmp> /*static*/ BiTree::Node const * const & BiTree::_findNode( const TCmp& val, BiTree::Node const * const & p ) // Return reference to the pointer field which would point to node containing val. { if ( p == NULL || p->val == val ) return p ; else if ( val < p->val ) return _findNode( val, p->left ) ; else return _findNode( val, p->right ) ; } template< typename TCmp> inline BiTreeIterator BiTree::begin() const // Return an iterator pointing to first (i.e. smallest) element in binary tree. { return BiTreeIterator( _root ) ; } template< typename TCmp> inline BiTreeIterator BiTree::end() const // Return an iterator with a value that represents one ++ past the last element in the tree. { return BiTreeIterator( NULL ) ; } // // BiTreeIterator methods // template< typename TCmp> inline const BiTreeIterator& BiTreeIterator::operator++() // Preincrement. Move the iterator to the next item in an inorder traversal. { if ( ! _stk.empty() ) { const Node* p= _stk.top() ; _stk.pop() ; if ( p->right ) _pushLeftmosts( p->right ) ; } return *this ; } template< typename TCmp> inline BiTreeIterator BiTreeIterator::operator++( int ) // Postincrement. { BiTreeIterator it( *this ) ; (*this)++ ; return it ; } template< typename TCmp> inline void BiTreeIterator::_pushLeftmosts( const Node* p ) // Push all left pointers from p downward. { while ( p ) { _stk.push( p ) ; p= p->left ; } } /////////////////////////////////// // A little demo. /////////////////////////////////// #include #include #include #include void demo() { int ar[]= { 30, 20, 25, 60, 80, 120, 22, 10, 75, 72 } ; int N= 10 ; BiTree bt ; int i ; // Put stuff in. for ( i=0 ; i < N ; ++i ) bt.insert( ar[i] ) ; // Are they really there? for ( i=0 ; i < N ; ++i ) assert( bt.isPresent( ar[i] ) ) ; // No false positives? for ( i=0 ; i < N ; ++i ) assert( ! bt.isPresent( ar[i] + 1 ) ) ; // Iterate through it. for ( BiTree::const_iterator it= bt.begin() ; it != bt.end() ; ++it ) cout << "it at: " << *it << endl ; } int main() { // Check out the traits. BiTree::const_iterator::value_type x= 3.14 ; iterator_traits< BiTree::const_iterator >::value_type e= 1.14 ; // Run a demo. demo() ; cout << "Done.\n" << endl ; return 0 ; }