title: BinaryTree Data structure with methods
body: <p>I implemented a binary tree data structure. The data structure allows a binary tree to be built from a list (elements are inserted from left to right). How can I optimize insertElement? At the moment, it is recursive, so if tree is deep, it will run out of memory. How can I make it tail-recursive or even end-recursive?</p>
  
  <pre><code>public class Node {
  
      private int value;
      private boolean isLeaf;
  
      public Node (int value, boolean isLeaf){
          this.value = value;
          this.isLeaf = isLeaf;
      }
  
      public int getValue(){
          return value;
      }
  
      public void setLeaf(boolean value){
          this.isLeaf = value;
      }
      public boolean isLeaf(){
          return isLeaf;
      }
  
  }
  
  
  
  public class BinaryTree {
  
      Node root;
      BinaryTree left_child;
      BinaryTree right_child;
  
      public BinaryTree(){
  
      }
      public BinaryTree(Node root, BinaryTree left_child, BinaryTree right_child){
          this.root = root;
          this.left_child = left_child;
          this.right_child = right_child;
      }
  
      public BinaryTree insertElement(int element){
          if (root==null)
              return new BinaryTree(new Node(element, true), null, null);
          else {
              if (root.isLeaf()){
                  root.setLeaf(false);
                  if (element &lt; root.getValue())
                      return new BinaryTree(root, new BinaryTree(new Node(element, true), null, null), null);
                  else
                      return new BinaryTree(root, null, new BinaryTree(new Node(element, true), null, null));
              } else {
                  if (element &lt; root.getValue())
                      if (left_child!=null)
                          return new BinaryTree(root, left_child.insertElement(element), right_child);
                      else
                          return new BinaryTree(root, new BinaryTree(new Node(element, true), null, null), right_child);
                  else
                      if (right_child!=null)
                          return new BinaryTree(root, left_child, right_child.insertElement(element));
                      else
                          return new BinaryTree(root, left_child, new BinaryTree(new Node(element, true), null, null));
              }
          }
      }
  
      public BinaryTree getLeftChild(){
          return left_child;
      }
  
      public BinaryTree getRightChild(){
          return right_child;
      }
  
      public void setLeftChild(BinaryTree tree){
          this.left_child = tree;
      }
  
      public void setRightChild(BinaryTree tree){
          this.right_child = tree;
      }
  
      public BinaryTree buildBinaryTree(int[] elements){
          if (elements.length==0)
              return null;
          else{
              BinaryTree tree = new BinaryTree(new Node(elements[0], true), left_child, right_child);
              for (int i=1;i&lt;elements.length;i++){
                  tree = tree.insertElement(elements[i]);
              }
              return tree;
          }
      }
  
      public void traversePreOrder(){
          if (root!=null)
              System.out.print(root.getValue() + " ");
          if (left_child!=null)
              left_child.traversePreOrder();
          if (right_child!=null)
              right_child.traversePreOrder();
      }
  
      public void traverseInOrder(){
          if (left_child!=null)
              left_child.traverseInOrder();
          if (root!=null)
              System.out.print(root.getValue() + " ");
          if (right_child!=null)
              right_child.traverseInOrder();
      }
      public void traversePostOrder(){
          if (left_child!=null)
              left_child.traversePostOrder();
          if (right_child!=null)
              right_child.traversePostOrder();
          if (root!=null)
              System.out.print(root.getValue() + " ");
      }
  
      public static void main(String[] args){
          int[] elements = new int[]{5,7,2,1,4,6,8};
          BinaryTree tree = new BinaryTree();
          tree = tree.buildBinaryTree(elements);
          tree.traversePreOrder();
          System.out.println();
          tree.traverseInOrder();
          System.out.println();
          tree.traversePostOrder();
          System.out.println();
      }
  
  }
  </code></pre>