Discussion 2: PA1 Siarhei Vishniakou CSE 100 Summer 2014 Files for PA1 • BST.hpp – Represents entire binary search tree – Contains pointer to root node and a bunch of methods • BSTIterator.hpp – Represents an iterator over the binary search tree • BSTNode.hpp – Represents a single node of binary search tree – Contains pointers to left child, right child, and parent, and contains a Data object – Also has successor() method • test_BST.cpp – Main script used for testing • Makefile Understanding the code • Start with test_BST.cpp – See how the tree and iterators are being used • Look at BSTIterator, BSTNode, BST • Implementation (my recommendation) – BSTIterator, BST, BSTNode, in that order • successor function is hardest in my opinion Inorder traversal • Elements of the BST should be accessed in increasing arithmetic order 3 • Insert order: 4 1 – 3, 4, 1, 100, -33 • Order should be – -33, 1, 3, 4, 100 -33 100 Another example • Insert order: – 30, 20, 70, 10, 50, 40, 60 • Traversal in-order should be: 30 – 10, 20, 30, 40, 50, 60, 70 70 20 10 50 40 60 BST.hpp • insert, find : return iterator – Create a new iterator every time you return • Code is almost identical! Returning std::pair • virtual std::pair<iterator,bool> insert(const Data& item) • An std::pair provides a way to return two arguments from one function To return an std::pair: • return std::make_pair(iterator(node), true); Iterators • An iterator object has: – A pointer to the object that it is iterating over – A ++ operator so that you can go on to next object • That’s about it • Doesn’t really add any new functionality • Provides a consistent way to iterate over objects Iterators • There is no object that contains a collection of references to all of the created nodes • BST: – Contains pointer to root node • BSTNode: – Contains pointers to left, right children and parent • BSTIterator: – Contains ++ method and a reference to current object Iterators • Example traversal with iterators: cout << "simple traversal test:" << endl; for(BST<int>::iterator it = b.begin(); it != b.end(); ++it) { cout << *it << "," << endl; } • When ++it executes, successor() function is called on the current node • Current node starts at the node with the minimum Data value • b.end returns a null pointer Iterators • You don’t really NEED iterators cout << "simple traversal test:" << endl; • Instead of for(BST<int>::iterator it = b.begin(); it != b.end(); ++it) { } cout << *it << "," << endl; ,you could iterate over nodes directly by calling “successor” method until it returns a null pointer • You would have to modify few return types and protection levels for some variables in this homework • Iterators are a convenience feature Iterators • An iterator does not know – What is a root node – Where the iteration has been – How many more times you can iterate • An iterator does know – What is the current object being examined – What should be the next object to be examined Tips on homework • • • • test_BST is good, but write your own test code there as well Add lots of cout statements Example: just print out the tree, without any error checks Segmentation fault – most likely you are trying to access a null pointer • Infinite loop – your tree traversal is incorrect – Add return statements to break up the function and see which piece of code causes it gdb • Use gdb if segmentation fault • Turn off compiler optimizations: • Change CXX flag from –O2 to –O0 in the Makefile BSTIterator constructor • Use keyword “this” to access the fields of current object • This will allow you to distinguish between input argument and class field Destructors • I have not tested this, but this is how I would do it: • Add a destructor for BSTNode – Inside, delete left and right children if exist* – According to Kacy, it’s OK to delete nullptr • For clear method for BST: – Delete root node, reset size • Destructor for BST: – Call “clear” Updated: virtual? • If destructor is virtual, then subclasses can override the destructor for proper cleanup • In the case of BSTNode for the current homework, it does not matter if destructor is declared to be virtual • If there are plans to inherit from BSTNode in future classes, however, the destructor should be declared virtual to allow override and therefore proper deletion of future subclass objects • In short, yes, make it virtual in case there is a subclass BST functions: insert Insert(new_data) • If no root yet, insert at root • Current = root • While current.data not equal to new_data 30 – If new_data < current.data • If left of current is null – Insert here, return left of current (newly created) 20 • Else – Current = left of current – Similar for current.data < new_data • Return current 10 70 BST functions: find • Almost exactly like previous slide! BST functions: begin • Needs to return the smallest (<) element in the tree • Return leftmost child, starting from the root node • (probably a while loop) BSTNode function: successor Few cases to consider • Does it have a right child? – If so, keep taking lefts of it • No right child: • Has a parent? 30 – If not, this is the max element 70 20 • If it is left child of parent, – parent is the successor • If it is right child of parent: 10 50 – Keep going up until hit a left child link 40 60 Return typename • Why is the reason to use “typename”? • What is the difference between line 150 and 151? • Either one compiles and runs correctly for me • I will post this question on piazza, perhaps other TA’s can clarify Finally • There are tons of resources online – Lecture notes from other schools – Applets and web apps for visualization – Even source code • Use them! This is how you would be doing things at your job in the future