I am pretty new to trees, and I am trying to create kind of a "leaf iterator". I'm thinking it should put all nodes that does not have a .left
and .right
value onto a stack, but I'm not sure how or even if it's the right thing to do. I have tried searching for it, but every example I come over starts with going to the leftmost leaf, and going p = node.parent
, and I am avoiding linking to the node's parent.
I don't understand how I can repeatedlty start from the root and go through the vines without visiting the same vines over and over.
EDIT
I see people suggests using a recursive method to solve this, and I agree now. But I have been banging my head trying to find the solution for an iterator-class-way to do this for a while, and I still would like to know if that's possible, and how!
Most people use a binary tree to do an efficient insertion sort. Otherwise, they would use a collection. To print in sorted order, you should iterate left, print the node, then iterate right.
Postorder Traversal − This traversal to find the leaf node will use iteration. We will use a stack to store data and traverse the tree in a postorder manner (first right subtree then left subtree and then root) and print leaf nodes.
Use recursion:
public void visitNode(Node node) {
if(node.left != null) {
visitNode(node.left);
}
if(node.right != null) {
visitNode(node.right);
}
if(node.left == null && node.right == null) {
//OMG! leaf!
}
}
start it by supplying root
:
visitNode(root);
In order to translate this into an Iterator<Node>
you'll have to translate recursion to loop and then to traversal with state. Non-trivial, but should give you a lot of fun.
class Node {
public Node left = null;
public Node right = null;
// data and other goodies
}
class Tree {
public Node root = null;
// add and remove methods, etc.
public void visitAllLeaves(Node root) {
// visit all leaves starting at the root
java.util.Stack<Node> stack = new java.util.Stack<Node>();
if (root == null) return; // check to make sure we're given a good node
stack.push(root);
while (!stack.empty()) {
root = stack.pop();
if (root.left == null && root.right == null) {
// this is a leaf
// do stuff here
}
if (root.left != null) {
stack.push(root.left);
}
if (root.right != null) {
stack.push(root.right);
}
}
}
}
I'm not sure if the above code works, but that's somewhere along the lines of what needs to be done. Another option is javax.swing.TreeModel (half-joking).
Here is how one could implement an Iterator that would only return the leaf nodes, i.e. nodes without a left or right subtree.
The iterator searches for leaf nodes in the tree by doing a depth-first search, remembering the current state of the search in a stack and "pausing" when it has found a leaf node (see fetchNext() method).
The search is resumed when the client "consumes" the leaf node by calling next().
class Node {
public Node left;
public Node right;
}
class LeaveIterator implements Iterator<Node> {
private final Stack<Node> stack = new Stack<>();
private Node nextNode = null;
public LeaveIterator(Node root) {
if (root != null) {
stack.push(root);
nextNode = fetchNext();
}
}
private void fetchNext() {
Node next = null;
while (!stack.isEmpty() && next == null) {
Node node = stack.pop();
if (node.left == null && node.right == null) {
next = node;
}
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
return next;
}
public boolean hasNext() {
return nextNode != null;
}
public Node next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Node n = nextNode;
nextNode = fetchNext();
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With