Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Construct a tree structure from list of string paths

Tags:

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.

like image 296
sushant Avatar asked Jun 17 '09 07:06

sushant


People also ask

How many paths does a tree have?

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.

How to print all root to leaf paths?

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.


1 Answers

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 
like image 146
dfa Avatar answered Sep 23 '22 21:09

dfa