import java.util.Iterator; /** * A simple implementation of a binary tree. * Note that there is effectively no distinction between * a tree object and a node object - a tree object can * equivalently be thought of as the node object that is * the root of that tree. */ public class BinaryTree implements Iterable { // data item at the root private T value; // left subtree (or null if no left subtree) private BinaryTree left; // right subtree (or null if no right subtree) private BinaryTree right; // parent tree (or null if a root node) private BinaryTree parent; // construct a leaf node public BinaryTree(T value) { this.value = value; } // construct an interior node public BinaryTree(T value, BinaryTree left, BinaryTree right) { this.value = value; setLeft(left); setRight(right); } // get a pre-order iterator for the tree @Override public Iterator iterator() { return new PreorderIterator(this); } // set the left subtree (may be null to remove left subtree) public void setLeft(BinaryTree newLeft) { if (left != null) { // detach the existing subtree left.parent = null; } left = newLeft; if (left != null) { left.parent = this; // fix the new subtree parent } } // set the right subtree (may be null to remove right subtree) public void setRight(BinaryTree newRight) { if (right != null) { // detach the existing subtree right.parent = null; } right = newRight; if (right != null) { right.parent = this; // fix the new subtree parent } } public void setValue(T newVal) { value = newVal; } public T value() { return value; } public BinaryTree left() { return left; } public BinaryTree right() { return right; } public BinaryTree parent() { return parent; } // check if this is a root node (no parent) public boolean isRoot() { return parent == null; } // check if this is a leaf node (no children) public boolean isLeaf() { return left == null && right == null; } // get root of the tree that this node is part of public BinaryTree root() { if (this.isRoot()) { return this; } return this.parent.root(); } // get the number of nodes in this tree public int size() { if (this.isLeaf()) { return 1; } else if (left == null) { return 1 + right.size(); } else if (right == null) { return 1 + left.size(); } else { return 1 + right.size() + left.size(); } } // get depth of this node (path length from root to this node) public int depth() { if (this.isRoot()) { return 0; } else { return parent.depth() + 1; } } // get height of tree (maximum path length to some descendant) public int height() { if (this.isLeaf()) { return 0; } else if (left == null) { return right.height() + 1; } else if (right == null) { return left.height() + 1; } else { return Math.max(left.height(), right.height()) + 1; } } // check whether this is a full tree (all non-leaves have two children) public boolean isFull() { if (this.isLeaf()) { return true; } else if (left == null || right == null) { return false; } else { return left.isFull() && right.isFull(); } } // basic test of the BinaryTree class public static void main(String[] args) { BinaryTree two = new BinaryTree(2); BinaryTree three = new BinaryTree(3, null, two); BinaryTree eight = new BinaryTree(8); BinaryTree five = new BinaryTree(5, three, eight); System.out.println(five.left().right().parent().parent().right().value()); System.out.println(five.size()); } }