/** * A simple implementation of a binary tree. */ public class BinaryTree { // value stored at this node private T value; // parent node (or null if a root node) private BinaryTree parent; // left subtree - might be an empty tree, but never null private BinaryTree left; // right subtree - might be an empty tree, but never null private BinaryTree right; // construct an empty tree (i.e., a tree with zero nodes) public BinaryTree() { value = null; // null value designates an empty tree parent = null; left = this; right = this; } // construct a leaf node (i.e., a node with empty left and right subtrees) public BinaryTree(T value) { if (value == null) { // non-empty nodes cannot store null throw new IllegalArgumentException("value cannot be null"); } this.value = value; parent = null; left = new BinaryTree(); // left and right are empty subtrees right = left; } // construct an interior node public BinaryTree(T value, BinaryTree left, BinaryTree right) { this(value); // first call leaf constructor if (left != null) { // allow left parameter to be null, signifiying empty subtree setLeft(left); } if (right != null) { // allow right parameter to be null, signifiying empty subtree setRight(right); } } public void setLeft(BinaryTree newLeft) { if (!isEmpty()) { // do nothing on empty trees left.setParent(null); // detach the existing subtree left = newLeft; left.setParent(this); // fix the new subtree parent } } public void setRight(BinaryTree newRight) { if (!isEmpty()) { right.setParent(null); right = newRight; right.setParent(this); } } private void setParent(BinaryTree newParent) { if (!isEmpty()) { // do nothing on empty trees parent = newParent; } } // get number of nodes in the tree public int size() { if (isEmpty()) { return 0; } else { return left.size() + right.size() + 1; } } // get root of tree that this node is part of public BinaryTree root() { if (parent == null) { return this; } return parent.root(); } // path length from root to this node public int depth() { if (parent == null) { return 0; } return parent.depth() + 1; } // maximum path length to some descendant public int height() { if (isEmpty()) { return -1; } return 1 + Math.max(left.height(), right.height()); } // a full binary tree is a tree in which all non-leaves // have two children public boolean isFull() { if (isEmpty()) { return true; } else if (left.height() != right.height()) { return false; } else { return left.isFull() && right.isFull(); } } // check if this is an empty tree public boolean isEmpty() { return value == null; } // check if this is a root node public boolean isRoot() { return parent == null; } // check if this is a leaf node public boolean isLeaf() { return left.isEmpty() && right.isEmpty(); } public T value() { return value; } public void setValue(T newVal) { value = newVal; } public BinaryTree left() { return left; } public BinaryTree right() { return right; } public BinaryTree parent() { return parent; } public static void main(String[] args) { BinaryTree one = new BinaryTree(1); BinaryTree two = new BinaryTree(2); BinaryTree three = new BinaryTree(3, null, one); BinaryTree four = new BinaryTree(4, three, two); System.out.println(four.right().value()); System.out.println(four.left().right().value()); } }