summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-13 23:11:36 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-13 23:11:36 -0400
commit9adff31e86603493c2a245e1e803d951675d5e00 (patch)
tree7374a6e4657333881db5621fbf23e18617470329 /BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java
parentba07771f8333f1b098ab8a9ec9fec886b72b9cc0 (diff)
Implemented new tree abstraction
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java235
1 files changed, 235 insertions, 0 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java
new file mode 100644
index 0000000..d9938d4
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java
@@ -0,0 +1,235 @@
+package bjc.utils.funcdata;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+
+import bjc.utils.funcdata.bst.TreeLinearizationMethod;
+
+/**
+ * A node in a homogenous tree.
+ *
+ * @author ben
+ *
+ * @param <ContainedType>
+ */
+public class Tree<ContainedType> implements ITree<ContainedType> {
+ private ContainedType data;
+ private IFunctionalList<ITree<ContainedType>> children;
+
+ private boolean hasChildren;
+
+ private int childCount;
+
+ /**
+ * Create a new leaf node in a tree
+ *
+ * @param leafToken
+ * The data to store as a leaf node
+ */
+ public Tree(ContainedType leafToken) {
+ data = leafToken;
+
+ hasChildren = false;
+ }
+
+ /**
+ * Create a new tree node with the specified children
+ *
+ * @param leafToken
+ * The data to hold in this node
+ * @param childrn
+ * A list of children for this node
+ */
+ @SafeVarargs
+ public Tree(ContainedType leafToken, ITree<ContainedType>... childrn) {
+ data = leafToken;
+
+ hasChildren = true;
+
+ childCount = 0;
+
+ children = new FunctionalList<>();
+
+ for (ITree<ContainedType> child : childrn) {
+ children.add(child);
+
+ childCount++;
+ }
+ }
+
+ private Tree(ContainedType leafToken,
+ IFunctionalList<ITree<ContainedType>> childrn) {
+ data = leafToken;
+
+ hasChildren = true;
+
+ childCount = childrn.getSize();
+
+ children = childrn;
+ }
+
+ @Override
+ public void addChild(ITree<ContainedType> child) {
+ if (hasChildren == false) {
+ hasChildren = true;
+
+ children = new FunctionalList<>();
+ }
+
+ childCount++;
+
+ children.add(child);
+ }
+
+ @Override
+ public <TransformedType> TransformedType transformHead(
+ Function<ContainedType, TransformedType> transformer) {
+ return transformer.apply(data);
+ }
+
+ @Override
+ public int getChildrenCount() {
+ return childCount;
+ }
+
+ @Override
+ public <TransformedType> TransformedType transformChild(int childNo,
+ Function<ITree<ContainedType>, TransformedType> transformer) {
+ if (childNo < 0 || childNo > (childCount - 1)) {
+ throw new IllegalArgumentException(
+ "Child index #" + childNo + " is invalid");
+ }
+
+ return transformer.apply(children.getByIndex(childNo));
+ }
+
+ @Override
+ public <NewType, ReturnedType> ReturnedType collapse(
+ Function<ContainedType, NewType> leafTransform,
+ Function<ContainedType, Function<IFunctionalList<NewType>, NewType>> nodeCollapser,
+ Function<NewType, ReturnedType> resultTransformer) {
+
+ return resultTransformer
+ .apply(internalCollapse(leafTransform, nodeCollapser));
+ }
+
+ protected <NewType> NewType internalCollapse(
+ Function<ContainedType, NewType> leafTransform,
+ Function<ContainedType, Function<IFunctionalList<NewType>, NewType>> nodeCollapser) {
+ if (hasChildren) {
+ Function<IFunctionalList<NewType>, NewType> nodeTransformer = nodeCollapser
+ .apply(data);
+
+ IFunctionalList<NewType> collapsedChildren = children
+ .map((child) -> {
+ return child.collapse(leafTransform, nodeCollapser,
+ (subTreeVal) -> subTreeVal);
+ });
+
+ return nodeTransformer.apply(collapsedChildren);
+ }
+
+ return leafTransform.apply(data);
+ }
+
+ @Override
+ public ITree<ContainedType> flatMapTree(
+ Function<ContainedType, ITree<ContainedType>> mapper) {
+ if (hasChildren) {
+ ITree<ContainedType> flatMappedData = mapper.apply(data);
+
+ children.map((child) -> child.flatMapTree(mapper))
+ .forEach((child) -> flatMappedData.addChild(child));
+
+ return flatMappedData;
+ }
+
+ return mapper.apply(data);
+ }
+
+ @Override
+ public void selectiveTransform(Predicate<ContainedType> nodePicker,
+ UnaryOperator<ContainedType> transformer) {
+ if (hasChildren) {
+ children.forEach((child) -> child
+ .selectiveTransform(nodePicker, transformer));
+ } else {
+ data = transformer.apply(data);
+ }
+ }
+
+ @Override
+ public <MappedType> ITree<MappedType> transformTree(
+ Function<ContainedType, MappedType> transformer) {
+ if (hasChildren) {
+ IFunctionalList<ITree<MappedType>> transformedChildren = children
+ .map((child) -> child.transformTree(transformer));
+
+ return new Tree<>(transformer.apply(data),
+ transformedChildren);
+ }
+
+ return new Tree<>(transformer.apply(data));
+ }
+
+ @Override
+ public void traverse(TreeLinearizationMethod linearizationMethod,
+ Consumer<ContainedType> action) {
+ if (hasChildren) {
+ switch (linearizationMethod) {
+ case INORDER:
+ if (childCount != 2) {
+ throw new IllegalArgumentException(
+ "Can only do in-order traversal for binary trees.");
+ }
+
+ children.getByIndex(0).traverse(linearizationMethod,
+ action);
+
+ action.accept(data);
+
+ children.getByIndex(1).traverse(linearizationMethod,
+ action);
+ break;
+ case POSTORDER:
+ children.forEach((child) -> child
+ .traverse(linearizationMethod, action));
+
+ action.accept(data);
+ break;
+ case PREORDER:
+ action.accept(data);
+
+ children.forEach((child) -> child
+ .traverse(linearizationMethod, action));
+ break;
+ default:
+ break;
+
+ }
+ } else {
+ action.accept(data);
+ }
+ }
+
+ @Override
+ public <MappedType> ITree<MappedType> rebuildTree(
+ Function<ContainedType, MappedType> leafTransformer,
+ Function<ContainedType, MappedType> operatorTransformer) {
+ if (hasChildren) {
+ IFunctionalList<ITree<MappedType>> mappedChildren = children
+ .map((child) -> {
+ return child.rebuildTree(leafTransformer,
+ operatorTransformer);
+ });
+
+ return new Tree<>(operatorTransformer.apply(data),
+ mappedChildren);
+ }
+
+ return new Tree<>(leafTransformer.apply(data));
+ }
+
+}