import java.util.Iterator;
import java.util.Stack;

public class TreeIterator {
  public static void main (String [] args) {
    Tree tree = new Tree();

    for(int val: new int[] { 4, 2, 6, 1, 3, 9, 5, 8, 7}) {
			tree.insert(val);
		}
    
    Out.println("Ausgabe Inorder (rekursiv)");
    tree.print();
    
    Out.println("Ausgabe Inorder (Iterator)");
    for(Integer val: tree) Out.println(val);
  }
}

class Tree implements Iterable<Integer> {
  private Node root;
  public void insert(int val) {
    root = insert0(root, val);
  }
  private Node insert0(Node p, int val) {
    if(p == null)
      p = new Node(val);
    else if(val <= p.val)
      p.left = insert0(p.left, val);
    else if(val > p.val)
      p.right = insert0(p.right, val);
    return p;
  }
  public void print() {
    print0(root);
  }
  void print0(Node p) {
    if(p != null) {
      print0(p.left);
      Out.println(p.val);
      print0(p.right);
    }
  }
  public Iterator<Integer> iterator() {
    return new MyIterator(root);
  }
}

class MyIterator implements Iterator<Integer> {
  // Inorder-Durchlauf
  // Schritt 1: im Baum ganz nach Links und alle Knoten auf Stack legen
  // Schritt 2: obersten Knoten vom Stack nehmen, ausgeben,
  //            und mit rechtem Teilbaum des Knoten bei Schritt 1 fortsetzen
  private Stack<Node> s = new Stack<Node>();
  public MyIterator(Node root) {
    subtree(root);
  }
  void subtree(Node p) {
    while(p != null) {
      s.push(p);
      p = p.left;
    }
  }
  public boolean hasNext() {
    return !s.empty();
  }
  public Integer next() {
    Node p = s.pop();
    subtree(p.right);
    return p.val;
  }
  public void remove() {
    throw new UnsupportedOperationException();
  }
}

class Node {
  int val;
  Node left, right;
  Node(int val) {
    this.val = val;
  }
}
