/*
Copyright 2010 Vivin Suresh Paliath
Distributed under the BSD License
*/
package com.laytonsmith.core;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class GenericTree<T> {
private GenericTreeNode<T> root;
public GenericTree() {
super();
}
public GenericTreeNode<T> getRoot() {
return this.root;
}
public void setRoot(GenericTreeNode<T> root) {
this.root = root;
}
public int getNumberOfNodes() {
int numberOfNodes = 0;
if (root != null) {
numberOfNodes = auxiliaryGetNumberOfNodes(root) + 1; //1 for the root!
}
return numberOfNodes;
}
private int auxiliaryGetNumberOfNodes(GenericTreeNode<T> node) {
int numberOfNodes = node.getNumberOfChildren();
for (GenericTreeNode<T> child : node.getChildren()) {
numberOfNodes += auxiliaryGetNumberOfNodes(child);
}
return numberOfNodes;
}
public boolean exists(GenericTreeNode<T> nodeToFind) {
return ( find(nodeToFind) != null );
}
public GenericTreeNode<T> find(GenericTreeNode<T> nodeToFind) {
GenericTreeNode<T> returnNode = null;
if (root != null) {
returnNode = auxiliaryFind(root, nodeToFind);
}
return returnNode;
}
private GenericTreeNode<T> auxiliaryFind(GenericTreeNode<T> currentNode, GenericTreeNode<T> nodeToFind) {
GenericTreeNode<T> returnNode = null;
if (currentNode.equals(nodeToFind)) {
returnNode = currentNode;
} else if (currentNode.hasChildren()) {
int i = 0;
while (returnNode == null && i < currentNode.getNumberOfChildren()) {
returnNode = auxiliaryFind(currentNode.getChildAt(i), nodeToFind);
i++;
}
}
return returnNode;
}
public boolean isEmpty() {
return ( root == null );
}
public List<GenericTreeNode<T>> build(GenericTreeTraversalOrderEnum traversalOrder) {
List<GenericTreeNode<T>> returnList = null;
if (root != null) {
returnList = build(root, traversalOrder);
}
return returnList;
}
public List<GenericTreeNode<T>> build(GenericTreeNode<T> node, GenericTreeTraversalOrderEnum traversalOrder) {
List<GenericTreeNode<T>> traversalResult = new ArrayList<GenericTreeNode<T>>();
if (traversalOrder == GenericTreeTraversalOrderEnum.PRE_ORDER) {
buildPreOrder(node, traversalResult);
} else if (traversalOrder == GenericTreeTraversalOrderEnum.POST_ORDER) {
buildPostOrder(node, traversalResult);
}
return traversalResult;
}
private synchronized void buildPreOrder(GenericTreeNode<T> node, List<GenericTreeNode<T>> traversalResult) {
traversalResult.add(node);
for (int i = 0; i < node.getNumberOfChildren(); i++) {
//for(GenericTreeNode<T> child : node.getChildren()) {
buildPreOrder(node.getChildAt(i), traversalResult);
}
}
private void buildPostOrder(GenericTreeNode<T> node, List<GenericTreeNode<T>> traversalResult) {
for (GenericTreeNode<T> child : node.getChildren()) {
buildPostOrder(child, traversalResult);
}
traversalResult.add(node);
}
public Map<GenericTreeNode<T>, Integer> buildWithDepth(GenericTreeTraversalOrderEnum traversalOrder) {
Map<GenericTreeNode<T>, Integer> returnMap = null;
if (root != null) {
returnMap = buildWithDepth(root, traversalOrder);
}
return returnMap;
}
public Map<GenericTreeNode<T>, Integer> buildWithDepth(GenericTreeNode<T> node, GenericTreeTraversalOrderEnum traversalOrder) {
Map<GenericTreeNode<T>, Integer> traversalResult = new LinkedHashMap<GenericTreeNode<T>, Integer>();
if (traversalOrder == GenericTreeTraversalOrderEnum.PRE_ORDER) {
buildPreOrderWithDepth(node, traversalResult, 0);
} else if (traversalOrder == GenericTreeTraversalOrderEnum.POST_ORDER) {
buildPostOrderWithDepth(node, traversalResult, 0);
}
return traversalResult;
}
private void buildPreOrderWithDepth(GenericTreeNode<T> node, Map<GenericTreeNode<T>, Integer> traversalResult, int depth) {
traversalResult.put(node, depth);
for (GenericTreeNode<T> child : node.getChildren()) {
buildPreOrderWithDepth(child, traversalResult, depth + 1);
}
}
private void buildPostOrderWithDepth(GenericTreeNode<T> node, Map<GenericTreeNode<T>, Integer> traversalResult, int depth) {
for (GenericTreeNode<T> child : node.getChildren()) {
buildPostOrderWithDepth(child, traversalResult, depth + 1);
}
traversalResult.put(node, depth);
}
@Override
public String toString() {
/*
We're going to assume a pre-order traversal by default
*/
String stringRepresentation = "";
if (root != null) {
stringRepresentation = build(GenericTreeTraversalOrderEnum.PRE_ORDER).toString();
}
return stringRepresentation;
}
public String toStringWithDepth() {
/*
We're going to assume a pre-order traversal by default
*/
String stringRepresentation = "";
if (root != null) {
stringRepresentation = buildWithDepth(GenericTreeTraversalOrderEnum.PRE_ORDER).toString();
}
return stringRepresentation;
}
}