I have a collection of string paths like ["x1/x2/x3","x1/x2/x4","x1/x5"] in a list. I need to construct a tree-like structure from this list which can be iterated to get a pretty printed tree. like this
x1 / \ x5 x2 / \ x3 x4
Any ideas/suggestions? I believe that the problem can be attacked first by processing the list of strings EDIT: The correct answer chosen was an elegant implementation, other suggestions were good too.
A tree with N vertices (or nodes) has N-1 edges, and since in a tree there is always a unique path between two vertices, and the total number of paths equals N(N-1)/2.
Use a path array path[] to store current root to leaf path. Traverse from root to all leaves in top-down fashion. While traversing, store data of all nodes in current path in array path[]. When we reach a leaf node, print the path array.
Follow an implementation of naive implementation of a visitable tree:
class Tree<T> implements Visitable<T> { // NB: LinkedHashSet preserves insertion order private final Set<Tree> children = new LinkedHashSet<Tree>(); private final T data; Tree(T data) { this.data = data; } void accept(Visitor<T> visitor) { visitor.visitData(this, data); for (Tree child : children) { Visitor<T> childVisitor = visitor.visitTree(child); child.accept(childVisitor); } } Tree child(T data) { for (Tree child: children ) { if (child.data.equals(data)) { return child; } } return child(new Tree(data)); } Tree child(Tree<T> child) { children.add(child); return child; } }
interfaces for Visitor Pattern:
interface Visitor<T> { Visitor<T> visitTree(Tree<T> tree); void visitData(Tree<T> parent, T data); } interface Visitable<T> { void accept(Visitor<T> visitor); }
sample implementation for Visitor Pattern:
class PrintIndentedVisitor implements Visitor<String> { private final int indent; PrintIndentedVisitor(int indent) { this.indent = indent; } Visitor<String> visitTree(Tree<String> tree) { return new IndentVisitor(indent + 2); } void visitData(Tree<String> parent, String data) { for (int i = 0; i < indent; i++) { // TODO: naive implementation System.out.print(" "); } System.out.println(data); } }
and finally (!!!) a simple test case:
Tree<String> forest = new Tree<String>("forest"); Tree<String> current = forest; for (String tree : Arrays.asList("x1/x2/x3", "x1/x2/x4", "x1/x5")) { Tree<String> root = current; for (String data : tree.split("/")) { current = current.child(data); } current = root; } forest.accept(new PrintIndentedVisitor(0));
output:
forest x1 x2 x3 x4 x5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With