public class SpeciesTree { // OVERVIEW: An immutable tree of Species. A tree has a root of type Species, and zero, one or two children, // each of which is a Tree. Typical SpeciesTrees are < root >, < root, child >, and < root, child, child >. private /*@non_null@*/ Species root; private SpeciesTree lchild; private SpeciesTree rchild; // Rep Invariant (c): // c != null // c.root != null // there are no cycles in the tree // i.e., no tree reachable from c.(lchild | rchild)* is the same object as c. // there is only one path from the root to a particular tree // i.e., no tree reachable from c.(lchild | rchild)* is reachable from c.(lchild | rchild)* // except using the exact same path. public SpeciesTree (/*@non_null@*/ Species r) // EFFECTS: Returns a new SpeciesTree with root r and no children. { root = r; lchild = null; rchild = null; } public SpeciesTree (/*@non_null@*/ Species r, SpeciesTree lc, SpeciesTree rc) // EFFECTS: Returns a new SpeciesTree with root r and two children, lc and rc. { root = r; lchild = lc; rchild = rc; } public /*@non_null@*/ Species getRoot () // EFFECTS: Returns the Species at the root of this tree. { return root; } public SpeciesTree getLeft () // EFFECTS: Returns the left child of this tree. { return lchild; } public SpeciesTree getRight () // EFFECTS: Returns the right child of this tree. { return rchild; } public int parsimonyValue () // EFFECTS: Returns the parsimony value of this tree. // (Note: a better design might put this in a separate class.) { int pvalue = 0; if (lchild != null) { pvalue += lchild.parsimonyValue (); pvalue += root.mutationDistance (lchild.getRoot ()); } if (rchild != null) { pvalue += rchild.parsimonyValue (); pvalue += root.mutationDistance (rchild.getRoot ()); } return pvalue; } public String toString () { return toStringIndent (0); } private /*@non_null@*/ String toStringIndent (int indent) // EFFECTS: Returns a string representation of this tree indented indent spaces. { String res = ""; for (int i = 0; i < indent; i++) { res += " "; } res += root.toString () + "\n"; if (lchild != null) { res += lchild.toStringIndent (indent + 3); } if (rchild != null) { res += rchild.toStringIndent (indent + 3); } return res; } }