public class RecursiveBinTree<E> implements BinTree<E> {
    
    private BinTreeNode<E> root = null;
    
    public boolean isEmpty() {  return this.root == null;  }
    
    public int size() { return size(this.root);  }
    private static <E> int size(BinTreeNode<E> node) {
        if (node == null) {  return 0;  }
        return 1 + size(node.left) + size(node.right);
    }

    public int height() {  return height(this.root);  }
    private static <E> int height(BinTreeNode<E> node) {
        if (node == null) {  return -1;  }
        return 1 + max(height(node.left), height(node.right));
    }
    private static int max(int a, int b) {  return a > b ? a : b;  }

    public java.util.List<E> preOrder() {
        java.util.List<E> res = new java.util.ArrayList<E>();
        if (this.root != null) {  preOrder(this.root, res);  }
        return res;
    }
    private static <E> void preOrder(BinTreeNode<E> node, java.util.List<E> res) {
        res.add(node.elem);
        if (node.left != null) {  preOrder(node.left, res);  }
        if (node.right != null) {  preOrder(node.right, res);  }
    }

    public java.util.List<E> inOrder() {
        java.util.List<E> res = new java.util.ArrayList<E>();
        if (this.root != null) {  inOrder(this.root, res);  }
        return res;
    }
    private static <E> void inOrder(BinTreeNode<E> node, java.util.List<E> res) {
        if (node.left != null) {  inOrder(node.left, res);  }
        res.add(node.elem);
        if (node.right != null) {  inOrder(node.right, res);  }
    }

    public java.util.List<E> postOrder() {
        java.util.List<E> res = new java.util.ArrayList<E>();
        if (this.root != null) {  postOrder(this.root, res);  }
        return res;
    }
    private static <E> void postOrder(BinTreeNode<E> node, java.util.List<E> res) {
        if (node.left != null) {  postOrder(node.left, res);  }
        if (node.right != null) {  postOrder(node.right, res);  }
        res.add(node.elem);
    }
    public static void main(String[] args) {
        RecursiveBinTree<Character> tree = new RecursiveBinTree<Character>();
        tree.root = new BinTreeNode<Character>('D',
                new BinTreeNode<Character>('B',
                        new BinTreeNode<Character>('A',null,null),
                        new BinTreeNode<Character>('C',null,null)
                ),
                new BinTreeNode<Character>('I',
                        new BinTreeNode<Character>('E',
                                null,
                                new BinTreeNode<Character>('G',
                                        new BinTreeNode<Character>('F', null, null),
                                        new BinTreeNode<Character>('H', null, null)
                                )
                        ),
                        null
                )
        );
        System.out.println(tree.preOrder());
        System.out.println(tree.inOrder());
        System.out.println(tree.postOrder());
    }
}
