// Purpose. Iterator design pattern lab // // Problem. The BST class can traverse itself, but, the client of the BST // cannot stop the traversal at will and interject application-specific // functionality. An Iterator class is a "partner" to a "container-like" // class that provides the level of access and control that a client might // need, while still maintaining the encapsulation of the original class. // John Lakos has asserted that the interface of a "container-like" class // is not "necessary and sufficient" until an Iterator capability is provided. // // Assignment. // o Declare a class Iterator // o The public interface of class Iterator should consist of - // Iterator( BST* ); // void first(); // void next(); // int isDone(); // Node& currentItem(); // o Make class Iterator a friend of class BST // o Add the following method to class BST // Iterator* createIterator(); // o Add the following to the end of main() - // create an Iterator object // in a for loop, traverse the BST by using Iterator's first(), next(), // isDone(), and currentItem() methods // in a second for loop, traverse the BST again // deallocate the Iterator object // o The BST::createIterator() implementation needs to create and return an // "appropriately initialized" instance of class Iterator // o The school solution private data members of class Iterator are: // BST* bst; // Node** list; // int nextNode; // o A strategy for the Iterator::first() implementation is - // create a dynamic array of type Node* whose size is equal to the number // of nodes in the BST // traverse the BST, copying each Node* into the dynamic array (the array // will now "mirror" the BST) // initialize a "next array element" data member to 0 // o Traversing the BST to initialize the dynamic array could be implemented // by defining a recursive function that looks a lot like the current // BST::traverse(Node*) method. The school solution implementation defines // the following private utility method - // void buildList( Node* current ) { // if (current->left != 0) buildList( current->left ); // list[nextNode++] = current; // if (current->right != 0) buildList( current->right ); // } // o Iterator::next() simply increments the "next array element" data member // o Iterator::currentItem() uses the "next array element" data member to // index into the dynamic array and then returns the dereferenced pointer // o Iterator::isDone() needs an implementation // o The dynamic array created in Iterator::first() needs to be deallocated if // a second call to Iterator::first() is made #include #include #include struct Node { int value; Node* left; Node* right; Node() { left = right = 0; } friend ostream& operator<< ( ostream& os, Node& n ) { return os << n.value; } }; class BST { private: Node* root; int size; public: BST() { root = 0; } void add( int in ) { if (root == 0) { root = new Node; root->value = in; size = 1; return; } add( in, root ); } void traverse() { traverse( root ); } private: void add( int in, Node* current ) { if (in < current->value) if (current->left == 0) { current->left = new Node(); current->left->value = in; size++; } else add( in, current->left ); else if (current->right == 0) { current->right = new Node(); current->right->value = in; size++; } else add( in, current->right ); } void traverse( Node* current ) { if (current->left != 0) traverse( current->left ); cout << current->value << " "; if (current->right != 0) traverse( current->right ); } }; void main( void ) { BST bst; time_t t; srand((unsigned) time(&t)); cout << "original: "; for (int i=0, val; i < 15; i++) { val = rand() % 49 + 1; cout << val << " "; bst.add( val ); } cout << "\ntraverse: "; bst.traverse(); cout << endl; } // original: 11 43 7 2 22 3 25 40 41 36 32 11 24 11 37 // traverse: 2 3 7 11 11 11 22 24 25 32 36 37 40 41 43 // Iterator: 2 3 7 11 11 11 22 24 25 32 36 37 40 41 43 // Iterator: 2 3 7 11 11 11 22 24 25 32 36 37 40 41 43