public void doInorder() { reset(); // move cursor to root if (root != null) doRecInorder(); } /* post: Do inorder traversal of subtree pointed to by cursor. Return cursor to starting point when done. */ public void doRecInorder() { if (hasLeft()) { moveLeft(); doRecInorder(); moveUp(); } value().doValueOp(); if (hasRight()) { moveRight(); doRecInorder(); moveUp(); } }It's very important to move the cursor back to where you started, otherwise the recursive solution will not work.
public void doPreorder() { reset(); // move cursor to root if (root != null) doRecPreorder(); } /* post: Do preorder traversal of subtree pointed to by cursor. Return cursor to starting point when done. */ public void doRecPreorder() { value().doValueOp(); if (hasLeft()) { moveLeft(); doRecPreorder(); moveUp(); } if (hasRight()) { moveRight(); doRecPreorder(); moveUp(); } }Only problem is can't take one step, and then stop and save where are so can come back later to do it. No problem with iterative since save stack.
Idea is top element on stack is element currently being examined. Must traverse subtree headed by node on stack as well as all subtrees headed by all other nodes on stack.
class BinaryTreePreorderIterator implements Iterator { protected BinaryTreeNode root; // root of tree protected Stack todo; // helper stack public BinaryTreePreorderIterator(BinaryTreeNode root) // post: constructs an iterator to traverse in preorder { todo = new StackList(); this.root = root; reset(); } public void reset() // post: resets the iterator to retraverse { todo.clear(); // stack is empty. Push on the current node. if (root != null) todo.push(root); } public boolean hasMoreElements() // post: returns true iff iterator is not finished { return !todo.isEmpty(); } public Object value() // pre: hasMoreElements() // post: returns reference to current value { return ((BinaryTreeNode)todo.peek()).value(); } public Object nextElement() // pre: hasMoreElements(); // post: returns current value, increments iterator { BinaryTreeNode old = (BinaryTreeNode)todo.pop(); Object result = old.value(); if (old.right() != null) todo.push(old.right()); if (old.left() != null) todo.push(old.left()); return result; } }
class BinaryTreeInorderIterator implements Iterator { protected BinaryTreeNode root; // root of tree protected Stack todo; // helper stack public BinaryTreeInorderIterator(BinaryTreeNode root) // post: constructs an iterator to traverse inorder { todo = new StackList(); this.root = root; reset(); } public void reset() // post: resets the iterator to retraverse { todo.clear(); // stack is empty. Push on nodes from root to // leftmost descendent BinaryTreeNode current = root; while (current != null) { todo.push(current); current = current.left(); } } public boolean hasMoreElements() // post: returns true iff iterator is not finished { return !todo.isEmpty(); } public Object value() // pre: hasMoreElements() // post: returns reference to current value { return ((BinaryTreeNode)todo.peek()).value(); } public Object nextElement() // pre: hasMoreElements(); // post: returns current value, increments iterator { BinaryTreeNode old = (BinaryTreeNode)todo.pop(); Object result = old.value(); // this node has no unconsidered left children. // if this node has a right child, // push the right child and its leftmost descendants: // now top elt of stack is next node to be visited. if (old.right() != null) { BinaryTreeNode current = old.right(); do { todo.push(current); current = current.left(); } while (current != null); } return result; } }
public Object nextElement() // pre: hasMoreElements(); // post: returns current value, increments iterator { BinaryTreeNode current = (BinaryTreeNode)todo.dequeue(); Object result = current.value(); if (current.left() != null) todo.enqueue(current.left()); if (current.right() != null) todo.enqueue(current.right()); return result; }Note similarity to preorder traversal!