All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dcutils.BinaryTree Maven / Gradle / Ivy

package dcutils;

// Import JDK Classes
import java.util.BitSet;

/**
 * A binary tree which sorts its children based on a comparable implementation.
* E.g.:
*
 * BinaryTree<Integer> tree = new BinaryTree<>();
 * tree.add(55);
 * tree.add(151);
 * tree.add(12);
 * tree.add(99);
 * tree.add(200);
 * tree.add(77);
 * tree.add(101);
 * 
* The above code produces a tree which looks like this:
*
 *    55
 *   /  \
 * 12    151
 *      /   \
 *    99     200
 *   /  \
 * 77    101
 * 
* This tree's height is 4, it's size is 7, and toString produces: [12, 55, 77, 99, 101, 151, 200] * @author dca */ public class BinaryTree> { @SuppressWarnings("unused") private class Node { private T data; private Node parent; private Node left; private Node right; public Node(T data, Node parent) { this.data = data; this.parent = parent; this.left = null; this.right = null; } // END constructor public boolean hasParent() { return null != this.parent; } // END hasParent public boolean hasLeft() { return null != this.left; } // END hasLeft public boolean hasRight() { return null != this.right; } // END hasRight public T getData() { return this.data; } // END getData public Node getParent() { return this.parent; } // END getParent public Node getLeft() { return this.left; } // END getLeft public Node getRight() { return this.right; } // END getRight public void setData(T data) { this.data = data; } // END setData public void setParent(Node parent) { this.parent = parent; } // END setParent public void setLeft(Node left) { this.left = left; } // END setLeft public void setRight(Node right) { this.right = right; } // ENDsetRight } // END inner class Node /** * A reference to the tree's root.
*/ private Node root; /** * Adds the supplied data element to the tree.
* @param data The supplied data element.
*/ public void add(T data) { if(null == root) { this.root = new Node(data, null); } else { add(data, this.root); } // END if/else } // END add private void add(T data, Node parent) { if(data.compareTo(parent.getData()) < 0) { if(null == parent.getLeft()) { parent.setLeft(new Node(data, parent)); } else { add(data, parent.getLeft()); } // END if/else } else { if(null == parent.getRight()) { parent.setRight(new Node(data, parent)); } else { add(data, parent.getRight()); } // END if/else } // END if/else } // END add /** * Removes all elements from the tree.
*/ public void clear() { this.root = null; System.gc(); } // END clear /** * Checks whether this tree contains any elements.
* @return true or false. */ public boolean isEmpty() { return null == this.root; } // END isEmpty /** * Returns the number of elements contained in the tree.
* @return int The number of elements. */ public int size() { return size(this.root); } // END size private int size(Node curr) { int size = 0; if(null != curr) { size++; if(null != curr.getLeft()) { size += size(curr.getLeft()); } // END if if(null != curr.getRight()) { size += size(curr.getRight()); } // END if } // END if return size; } // END size /** * Returns how far the farthest node from the root is.
* @return int The number of paths to the farthest node. */ public int height() { return height(this.root); } // END height private int height(Node curr) { int height = 0; if(null != curr) { height++; int left = 0; int right = 0; if(null != curr.getLeft()) { left = height(curr.getLeft()); } // END if if(null != curr.getRight()) { right = height(curr.getRight()); } // END if height += Math.max(left, right); } // END if return height; } // END height /** * Checks whether the supplied data elements is contained within the tree.
* @param item The supplied data element.
* @return true or false. */ public boolean contains(T item) { return contains(item, this.root); } // END contains private boolean contains(T item, Node curr) { if(null != curr) { if(item.equals(curr.getData())) { return true; } else { boolean left = false; boolean right = false; if(null != curr.getLeft()) { left = contains(item, curr.getLeft()); } // END if if(null != curr.getRight()) { right = contains(item, curr.getRight()); } // END if return left || right; } // END if/else } else { return false; } // END if/else } // END contains /** * Returns a BitSet specifying the pathways one would walk, starting from the root, in order to reach the supplied item.
* A bit set is a collection of zeros and ones.
* A zero means, follow the left child path.
* A one means, follow the right child path.
* @param item The supplied item.
* @return The bit set of pathways. */ public BitSet getPath(T item) { if(contains(item)) { String strPath = getPath(item, this.root, ""); strPath = strPath.replace("-", ""); BitSet bitPath = new BitSet(strPath.length()); for(int i = 0 ; i < strPath.length() ; ++i) { char c = strPath.charAt(i); if('1' == c) bitPath.set(i); } // END loop return bitPath; } else { return null; } // END if/else } // END getPath private String getPath(T item, Node curr, String path) { if(null != curr) { if(item.equals(curr.getData())) { return path + "-1"; } else { if(null != curr.getLeft()) { String left = getPath(item, curr.getLeft(), path + "0"); if(left.contains("-1")) return left; } // END if if(null != curr.getRight()) { String right = getPath(item, curr.getRight(), path + "1"); if(right.contains("-1")) return right; } // END if } // END if/else } // END if return path; } // END getPath /** * Returns an item from the tree by following the path of the supplied bit set.
* @param path The supplied bit set.
* @return The item found at the path of the pathway of the bit set. */ public T getItem(BitSet path) { return getItem(path, this.root, 0); } // END getItem private T getItem(BitSet path, Node curr, int bitIndex) { if(path.get(bitIndex)) { // path[bitIndex] == 1 if(-1 == path.nextSetBit(bitIndex + 1)) { // There are no more 1's following this return curr.getData(); } else { // There are more 1's following this return getItem(path, curr.getRight(), bitIndex + 1); } // END if/else } else { // path[bitIndex] == 0 return getItem(path, curr.getLeft(), bitIndex + 1); } // END if/else } // END getItem /** * Returns a string containing an array of data elements, * ordered by an in-order tree traversal.
* @return A string of ordered data elements of the tree. */ public String toStringInOrder() { return String.format("[%s]", toStringInOrder(this.root)); } // ENd toStringInOrder private String toStringInOrder(Node curr) { if(null != curr) { String string = curr.getData().toString(); if(null != curr.getLeft()) { string = String.format("%s, %s", toStringInOrder(curr.getLeft()), string); } // END if if(null != curr.getRight()) { string = String.format("%s, %s", string, toStringInOrder(curr.getRight())); } // END if return string; } else { return ""; } // END if/else } // END toStringInOrder /** * A string representation of this tree.
* This calls toStringInOrder.
* @return A string representation of the tree. * @see #toStringInOrder() */ @Override public String toString() { return toStringInOrder(); } // END toString } // END class BinaryTree




© 2015 - 2025 Weber Informatics LLC | Privacy Policy