ch18d-streel-iterator

Podcast Ch18d
• Title: Binary Search Tree Iterator
• Description: Additional operations first
and last; the BST iterator
• Participants: Barry Kurtz (instructor);
John Helfert and Tobie Williams
(students)
• Textbook: Data Structures for Java;
William H. Ford and William R. Topp
Additional STree Operations
• The method first() must return the smallest
element in the tree. In a binary search tree,
this element is in the leftmost node from root.
Additional STree Operations
(continued)
// returns the first (least) element in this
// binary search tree
public T first() {
STNode<T> nextNode = root;
// if the set is empty, return null
if (nextNode == null)
return null;
// first node is the furthest left from root
while (nextNode.left != null)
nextNode = nextNode.left;
return nextNode.nodeValue;
}
Additional STree Operations
(concluded)
• The method last() must return the largest
element in the tree. In a binary search tree, this
element is in the right-most node from root.
Implement the methods by starting at the root
and scan down the path of right children. The
value of the last node on the path is the
maximum value in the binary search tree.
• A binary search tree has best-case search time
O(log2n), worst-case time O(n), and average
time O(log2n).
Practice Coding
• Write the method last to find the largest item
in a BST?
The STree Iterator
• Implement an iterative traversal of
the elements using the STNode parent
field. The figure illustrates the order of
scan for the twenty elements in the search
tree. If the current iterator position is node
18, the next two elements are found by
moving up to the parent 20 and then down
the right subtree to node 22 and node 23.
From node 23 the next element is the root
node 25. We locate the value by scanning
up the path of parents four levels.
The STree Iterator (continued)
Student Question
• Given the tree
• Starting with #0, label the nodes in the order
they will be visited by an iterator.
Practice Problem
• Given the tree
• Starting with #0, label the nodes in the order
they will be visited by an iterator.
IteratorImpl Inner Class
private class IteratorImpl implements Iterator<T>
{
// set expectedModCount to the number of list
// changes at the time of iterator creation
private int expectedModCount = modCount;
// node of the last value returned by next()
// if that value was deleted by the iterator
// method remove()
private STNode<T> lastReturned = null;
// node whose value is returned a subsequent
// call to next()
private STNode<T> nextNode = null;
...
}
IteratorImpl Inner Class
(continued)
• The first node is the one far-left from the root.
Subsequent nodes are visited in LNR order.
IteratorImpl Inner Class (cont)
// constructor
IteratorImpl()
{
nextNode = root;
// if the tree is not empty, the first node
// inorder is the farthest node left from root
if (nextNode != null)
while (nextNode.left != null)
nextNode = nextNode.left;
}
// returns an iterator for the elements in the tree
public Iterator<T> iterator()
{
return new IteratorImpl();
}
Implementing next()
• If the right subtree is not empty, obtain the
next node in order by moving to the right
child and then moving left until
encountering a null subtree.
• If the right subtree is empty, obtain the
next node in order by following a chain of
parent references until locating a parent,
P, for which the current node, nodePtr, is a
left child. Node P is the next node in order.
Implementing next() (continued)
• When invoking next() from the node with the
tree's maximum value, the right subtree is
empty. As we move up the tree, we are always
a right child of our parent until we encounter the
root node, whose parent is null. In this situation,
the variable nextNode becomes null and we
have completed an iteration.
Implementing next() (continued)
// returns the next element in the iteration;
// throws NoSuchElementException if iteration
// has no more elements
public T next() {
// check that the iterator is in a consistent
// state; throws ConcurrentModificationException
// if it is not
checkIteratorState();
// check if the iteration has another element;
// if not, throw NoSuchElementException
if (nextNode == null)
throw new NoSuchElementException(
"Iteration has no more elements");
// save current value of next in lastReturned
lastReturned = nextNode;
// set nextNode to the next node in order
STNode<T> p;
Implementing next() (cont)
// have already processed the left subtree,
// and there is no right subtree; move up
// the tree, looking for a parent for
// which nextNode is a left child, stopping
// if the parent becomes null; a non-null
// parent is the successor; if parent is null,
// the original node was the last node inorder
p = nextNode.parent;
if (nextNode.right != null) {
// successor is the furthest left node of
// right subtree
nextNode = nextNode.right;
while (nextNode.left != null)
nextNode = nextNode.left;
}
Implementing next()
(concluded)
else
{
while (p != null && nextNode == p.right)
{
nextNode = p;
p = p.parent;
}
// if we were previously at the right-most
// node in the tree, nextNode = null
nextNode = p;
}
return lastReturned.nodeValue;
}
Implementing hasNext()
• The iteration is complete when nextNode
becomes null. The implementation of
hasNext() simply verifies that nextNode is
not equal to null.
// returns true if the tree has more
// unvisited elements
public boolean hasNext()
{
// elements remain if nextNode is not null
return nextNode != null;
}
Student Question
• How would you write a non-recursive iterator
if you did not have a parent pointer?
Practice Problem
• Write a non-recursive iterator assuming you
do not have a parent pointer?
• The previous discussion by John and Tobie
should be useful.