Basic implicit tree implementation in Java I tried starting off with something like below. Note that traversal etc. is not included, this is the portion for storage and modifications. It feels like this could be much more elegant at places but not exactly sure how. I'm mainly trying to improve how the code almost repeats for getters and setters for left and right subtrees.

import org.apache.commons.lang3.ArrayUtils;

public class Tree {      
  private int[] treeArray;
  private int depth;

  public Tree(int treeDepth) {
    this.depth = treeDepth;
    this.treeArray =  new int[(int) Math.pow(2, treeDepth)];
    treeArray[0] = Integer.MIN_VALUE;
  }

  public int returnRoot() {
    return treeArray[1];
  }

  public int[] getTreeArray() {
    return treeArray;
  }

  public int getDepth() {
    return depth;
  }

  public void setTreeArray(int[] treeArray) {
    this.treeArray = treeArray;
  }

  public Tree returnLeftSubTree() {
    if (depth == 0) return null;

    Tree ret = new Tree(depth - 1);
    for (int i  = 1; i &lt; depth; i ++) {
      for (int j  = 0; j &lt; depth - 1; j ++) {
        ret.getTreeArray()[(int) Math.pow(2, i - 1) + j]
            = treeArray[(int) Math.pow(2, i) + j];
      }
    }

    return ret;
  }

  public Tree returnRightSubTree() {
    if (depth == 0) return null;

    Tree ret = new Tree(depth - 1);
    for (int i  = 1; i &lt; depth; i ++) {
      for (int j  = 0; j &lt; depth - 1; j ++) {
        ret.getTreeArray()[(int) Math.pow(2, i - 1) + j]
            = treeArray[(int) (Math.pow(2, i) + Math.pow(2, i - 1)) + j];
      }
    }

    return ret;
  }

  public void setLeftSubTree(Tree leftSub) {
    if (leftSub.getDepth() &gt;= depth) {
      this.treeArray = ArrayUtils.addAll(
          this.treeArray,
          new int[(int) (Math.pow(2, leftSub.getDepth() + 1) - Math.pow(2, depth))]);
      this.depth = leftSub.getDepth() + 1;
    }

    for (int i  = 1; i &lt; depth; i ++) {
      for (int j  = 0; j &lt; depth - 1; j ++) {
        treeArray[(int) Math.pow(2, i) + j] =
            leftSub.getTreeArray()[(int) Math.pow(2, i - 1) + j];
      }
    }
  }

  public void setRightSubTree(Tree rightSub) {
    if (rightSub.getDepth() &gt;= depth) {
      this.treeArray = ArrayUtils.addAll(
          this.treeArray,
          new int[(int) (Math.pow(2, rightSub.getDepth() + 1) - Math.pow(2, depth))]);
      this.depth = rightSub.getDepth() + 1;
    }

    for (int i  = 1; i &lt; depth; i ++) {
      for (int j  = 0; j &lt; depth - 1; j ++) {
        treeArray[(int) (Math.pow(2, i) + Math.pow(2, i - 1)) + j]
            = rightSub.getTreeArray()[(int) Math.pow(2, i - 1) + j];
      }
    }
  }
}
More efficient and accurate is a bit shift.

this.treeArray =  new int[(int) Math.pow(2, treeDepth)];
treeArray =  new int[1 &lt;&lt; treeDepth];


A test is in order for the top:

if (0 &gt; treeDepth || treeDepth &gt; 31) {
    throw new IllegalArgumentException();
}


The name returnRightSubTree is a bit irritating because of that return, synonymical yieldRightSubTree or get/create.

  public Tree returnLeftSubTree() {
    return yieldSubTree(false);
  }

  public Tree returnRightSubTree() {
    return yieldSubTree(true);
  }

  private Tree yieldSubTree(boolean right) {
    if (depth == 0) return null;

    Tree ret = new Tree(depth - 1);
    int[] trees = ret.getTreeArray();
    for (int i  = 1; i &lt; depth; i++) {
      int iTarget = 1 &lt;&lt; (i - 1);
      int iSource = (1 &lt;&lt; i) + (right ? 1 &lt;&lt; (i - 1)) : 0);
      for (int j  = 0; j &lt; depth - 1; j ++) {
        trees[iTarget + j] = trees[iSource + j];
      }
    }
    return ret;
  }


which could be faster using System.arraycopy:

  private Tree yieldSubTree(boolean right) {
    if (depth == 0) return null;

    Tree ret = new Tree(depth - 1);
    int[] trees = ret.getTreeArray();
    for (int i  = 1; i &lt; depth; i++) {
      int iTarget = 1 &lt;&lt; (i - 1);
      int iSource = (1 &lt;&lt; i) + (right ? 1 &lt;&lt; (i - 1)) : 0);
      System.arraycopy(trees, iSource, trees, iTarget, depth - 1);
    }
    return ret;
  }


The i dependent expression before the j loop. As you see, just as i++
one could have (but not necessarily):

    for (int i  = 1, iT = 1; i &lt; depth; i++, iT &lt;&lt;= 1) {
      //int iTarget = iT;
      int iSource = (iT &lt;&lt; 1) + (right ? iT : 0);


For the rest:

Tab indentation in java is 4. Historically a tab size of 3 was often for C/C++,
and for academic reasons: "there should be less long code with nesting in favour of
more methods" 4 was chosen; also as 8 was the archaic system tab size.

A tab size of 2 is still seen in XML/HTML, but I would refrain from that. Especially
as with lambdas one gets more unreadable indentations.