I am trying to figure out how to print a first-child next sibling tree. What I want is the following:
root
|
firstChild - sibling - sibling
|
child - sibling - sibling
I have the following code to add childs and siblings :
class Program
{
static void Main(string[] args)
{
GeneralTree<string> tree = new GeneralTree<string>();
tree.root = new TreeNode<string>
{
Data = "Root"
};
TreeNode<string> child = tree.addChild(tree.root, "Child");
tree.addSibling(child, "Sibling");
tree.print(tree.root);
}
}
class GeneralTree<T>
{
public TreeNode<T> root;
public TreeNode<T> addChild(TreeNode<T> parent, T data)
{
parent.FirstChild = new TreeNode<T>
{
Data = data,
NextSibling = parent.FirstChild
};
return parent.FirstChild;
}
public TreeNode<T> addSibling(TreeNode<T> sibling, T data)
{
sibling.NextSibling = new TreeNode<T>
{
Data = data,
FirstChild = sibling.NextSibling
};
return sibling.NextSibling;
}
int count = 0;
public void print(TreeNode<T> Node)
{
if(Node !=null)
{
Console.WriteLine(Node.Data);
print(Node.FirstChild);
++count;
Console.WriteLine(count);
print(Node.NextSibling);
}
}
}
class TreeNode<T>
{
public T Data { get; set; }
public TreeNode<T> FirstChild { get; set; }
public TreeNode<T> NextSibling { get; set; }
}
Does anyone now how to print that out?
Thanks in advance!
I choosed to merge TreeNode and GeneralTree in this way :
public class TreeNode<T>
{
public T data;
public List<TreeNode<T>> childs;
public TreeNode<T> firstChild()
{return childs.get(0);}
public void appendChild(TreeNode<T> child)
{childs.add(child);}
public void print() {/* ... */}
/* ... */
public static void main(String args[])
{ /* ... */}
}
Then, a way to write print() recursively :
public void print()
{
print(0);
}
public void print(int offset)
{
if (node == null) return; // nothing to print anymore
System.out.println(this.data); // printing the root data
TreeNode<T> lastChild=null;
String output = "";
for(Iterator<TreeNode<T>> i = childs.iterator(); i.hasNext(); )
{
lastChild = i.next();
if (output != "") output += " - ";
output += lastChild.data;
}
// length will be the next line offset
// (size of the current line output minus last item length
int length = output.length()-lastChild.toString().length;
// use a repeat() string function like this one :
output = org.apache.commons.lang.StringUtils.repeat(" ", length) + (length>0?"|":"") + output;
System.out.println (output);
lastChild.print(length);
}
}
Unfortunately I can't validate my code right now, If you have issues, please let me know.
Related
I did a code that take as input integers, for example: 123 11 200 1 100 150 2000 and need to output a binary tree, in this form:
┌1
┌11┤
│ └100
123┤
│ ┌150
└200┤
└2000
but in my code output is:
0┐
│ ┌1
│ ┌11┤
│ │ └100
└123┤
│ ┌150
└200┤
└2000
At he root appear a zero and I do not know why.
This is my code. I consider that the problem is in the add() method, but do not know how to solve it. I will be grateful for help.
public class TreeNode extends BinaryTree implements PrintableTree {
private int i;
private TreeNode leftChild;
private TreeNode rightChild;
public TreeNode(int i) {
this.i = i;
}
public TreeNode() {
}
#Override
public void add(int i) {
if (i > this.i) {
if (this.rightChild == null) {
this.rightChild = new TreeNode(i);
} else {
this.rightChild.add(i);
}
} else {
if (this.leftChild == null) {
this.leftChild = new TreeNode(i);
} else {
this.leftChild.add(i);
}
}
}
public int getI() {
return i;
}
public void setLeftChild(TreeNode leftChild) {
this.leftChild = leftChild;
}
public void setRightChild(TreeNode rightChild) {
this.rightChild = rightChild;
}
public TreeNode getLeftChild() {
return leftChild;
}
public TreeNode getRightChild() {
return rightChild;
}
#Override
public String prettyPrint() {
StringBuilderPlus builder = new StringBuilderPlus();
prettyPrint(builder, "", "", "", "");
return builder.toString();
}
public void print() {
StringBuilderPlus res = new StringBuilderPlus();
prettyPrint(res, "", "", "", "");
}
public void prettyPrint(StringBuilderPlus result, String prefix, String left, String mid, String right) {
String indent = " ".repeat(String.valueOf(i).length());
if (leftChild != null) {
leftChild.prettyPrint(result, prefix + left + indent, " ", "┌", "│");
}
result.appendLine(prefix + mid + i
+ " ┐┘┤".charAt((leftChild != null ? 2 : 0)
+ (rightChild != null ? 1 : 0)));
if (rightChild != null) {
rightChild.prettyPrint(result, prefix + right + indent, "│", "└", " ");
}
}
}
public class StringBuilderPlus {
private StringBuilder sb;
public StringBuilderPlus(){
sb = new StringBuilder();
}
public void append(String str)
{
sb.append(str != null ? str : "");
}
public void appendLine(String str)
{
sb.append(str != null ? str : "").append(System.getProperty("line.separator"));
}
public String toString()
{
return sb.toString();
}
}
class BinaryTree {
private TreeNode root;
public void Print() {
if (root != null) {
root.print();
}
}
public void add(int i) {
if (root == null) {
root = new TreeNode(i);
} else {
root.add(i);
}
}
}
public interface PrintableTree {
void add(int i);
String prettyPrint();
static PrintableTree getInstance() {
return new TreeNode();
}
}
Thank you for posting the rest of the code. Your issue is with the PrintableTree interface in method getInstance. You return a new TreeNode (it comes initialized with 0 as int is a primitive type and cannot be null). And then you add the rest of the nodes to that original node with 0. You most likely wanted to return a new BinaryTree instead. However you need to change your code as BinaryTree does not implement the PrintableTree interface.
Here are the changes necessary to fix it:
In PrintableTree.java
static PrintableTree getInstance() {
return new BinaryTree();
}
In BinaryTree.java
// notice the added implements
class BinaryTree implements PrintableTree {
// the rest of the class is fine, add this to the end
#Override
public String prettyPrint() {
if (root != null) {
return root.prettyPrint();
}
return "";
}
}
Also the class TreeNode does not need to extend BinaryTree as a node is not a tree (it doesn't make sense for the node the contain a value AND a root). If your assignment requires this relation then edit the code accordingly.
An abstract binary tree is to be created using a generic class. Each node has a string value as well as an initialCalculatedValue value. No changes should be made to the main class and a static inner class is to be included in the generic class. I'd like some advice on my code, as the main class is giving me error on accessing 'timesVisited' and 'values'. My code can't seem to access those variables.
Main class code:
public class Main{
public static void main(String[] args) {
WalkableTree<String, Integer> ast = new WalkableTree<>(0);
WalkableTree.Node<String, Integer> plus = ast.setRoot("+");
plus.setRightChild("20");
WalkableTree.Node<String, Integer> multiply = plus.setLeftChild("*");
multiply.setLeftChild("10");
WalkableTree.Node<String, Integer> bracketedPlus = multiply.setRightChild("+");
bracketedPlus.setLeftChild("3");
bracketedPlus.setRightChild("4");
// write visitor to display pre-order
System.out.println("Pre-order traversal:");
ast.walk(current -> {
if(current.timesVisited == 2)
System.out.print(current.value + " ");
});
System.out.println();
// write visitor to display in-order
System.out.println("In-order traversal:");
ast.walk(current -> {
if(current.timesVisited == 3)
System.out.print(current.value + " ");
});
System.out.println();
// write visitor to display post-order
System.out.println("Post-order traversal:");
ast.walk(current -> {
if(current.timesVisited == 4)
System.out.print(current.value + " ");
});
System.out.println();
}
}
Functional interface:
#FunctionalInterface
public interface Visitor<N> {
public void visit(N node);
}
Generic class:
public class WalkableTree <T, R> {
private T root = null;
private R initialCalculatedValue;
public static Node current;
public WalkableTree(R initialCalculatedValue) {
this.initialCalculatedValue = initialCalculatedValue;
}
public Node getRoot() {
return (Node) root;
}
public Node setRoot(T value) {
current = new Node(null,null,null,value,null,0);
return current;
}
public R getInitialCalculatedValue() {
return initialCalculatedValue;
}
public void setInitialCalculatedValue(R initialCalculatedValue) {
this.initialCalculatedValue = initialCalculatedValue;
}
protected void reset(Node node) {
node.timesVisited = 0;
node.calculatedValue = initialCalculatedValue;
reset((Node) node.leftChild);
reset((Node) node.rightChild);
}
public Node nextNode(Node node) {
node.timesVisited++;
if(node.timesVisited == 1)
return node;
if(node.timesVisited == 2)
return (Node) node.leftChild;
if(node.timesVisited == 3)
return (Node) node.rightChild;
if(node.timesVisited == 4)
return (Node) node.getParent();
return node;
}
public void walk(Visitor visitor) {
//Reset all the nodes in the tree
reset((Node) root);
//Set the current node to visit at the root of the tree
visitor.visit(root);
//Walking through the tree as long as the current node still exists
//If current node exists, let the visitor object visit the current node
//Current node is set to the next node using nextNode() method
while (this.current == current)
{
nextNode(current);
}
}
public static class Node<T, R> {
//Variables
Object leftChild;
Object rightChild;
Object parent;
T value;
R calculatedValue;
int timesVisited = 0;
public Node(Object leftChild, Object rightChild, Object parent, T value, R calculatedValue, int timesVisited) {
this.leftChild = leftChild;
this.rightChild = rightChild;
this.parent = parent;
this.value = value;
this.calculatedValue = calculatedValue;
this.timesVisited = timesVisited;
}
public Object getLeftChild() {
return leftChild;
}
public Node setLeftChild(T value) {
Node newLeft = new Node(null,null, current,value,0,0);
current = newLeft;
return current;
}
public Object getRightChild() {
return rightChild;
}
public Node setRightChild(T value) {
Node newRight = new Node(null,null, current,value,0,0);
current = newRight;
return current;
}
public Object getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public R getCalculatedValue() {
return calculatedValue;
}
public void setCalculatedValue(R calculatedValue) {
this.calculatedValue = calculatedValue;
}
public int getTimesVisited() {
return timesVisited;
}
public void setTimesVisited(int timesVisited) {
this.timesVisited = timesVisited;
}
}
}
Update the method in WalkableTree as below:
public void walk(Visitor<Node> visitor) {
//Reset all the nodes in the tree
reset((Node) root);
//Set the current node to visit at the root of the tree
visitor.visit((Node) root);
//Walking through the tree as long as the current node still exists
//If current node exists, let the visitor object visit the current node
//Current node is set to the next node using nextNode() method
while (this.current == current)
{
nextNode(current);
}
}
Basically, my problem with my code is that somewhere in its implementation it creates a blank node which is then inserted into my binary tree. This node exists, as my sizeOfTree method counts it as such.
The code works just fine, the only problem is the node.
OK, so here I have defined the TreeNode based on which the Binary Tree is constructed:
package hr.fer.oop.lab1.prob6;
public class TreeNode {
TreeNode left=null;
TreeNode right=null;
String data;
public TreeNode(String data) {
this.data=data;
}
}
And here is the rest of it:
package hr.fer.oop.lab1.prob6;
import hr.fer.oop.lab1.prob6.TreeNode;
public class BinaryTree {
TreeNode root;
public BinaryTree() {
TreeNode node = new TreeNode("");
root=node;
}
public void insert (String data) {
if (this.root==null) {
this.root=new TreeNode(data);
return;
}
else {
TreeNode node = this.root;
TreeNode parent = new TreeNode("");
while(node!=null) {
parent = node;
if (node.data.compareTo(data)<=0) {
node=node.left;
}
else{
node=node.right;
}
}
if (parent.data.compareTo(data)<=0) {
parent.left=new TreeNode(data);
}
else {
parent.right=new TreeNode(data);
}
}
return;
}
private boolean subTreeContainsData(TreeNode node, String data) {
if ((node.data).compareTo(data)<1E-15) return true;
TreeNode temp=new TreeNode("");
temp=node;
if((temp.left.data).equals("")&&(temp.right.data).equals("")) return false;
return (subTreeContainsData(temp.left, data)||subTreeContainsData(temp.right, data));
}
private boolean containsData(String data) {
return subTreeContainsData(root, data);
}
private int sizeOfSubTree(TreeNode node) {
if (node==null) return 0;
return 1 + sizeOfSubTree(node.left) + sizeOfSubTree(node.right);
}
public int sizeOfTree() {
return sizeOfSubTree(root);
}
private void writeSubTree(TreeNode node) {
if (node!=null) {
writeSubTree(node.left);
System.out.println(node.data);
writeSubTree(node.right);
}
return;
}
public void writeTree() {
writeSubTree(root);
}
private void reverseSubTreeOrder(TreeNode node) {
if (node==null) return;
TreeNode helpNode;
helpNode=node.left;
node.left=node.right;
node.right=helpNode;
reverseSubTreeOrder(node.left);
reverseSubTreeOrder(node.right);
}
public void reverseTreeOrder() {
reverseSubTreeOrder(root);
}
public static void main (String[] args) {
BinaryTree tree = new BinaryTree();
tree.insert("Jasna");
tree.insert("Ana");
tree.insert("Ivana");
tree.insert("Anamarija");
tree.insert("Vesna");
tree.insert("Kristina");
System.out.println("Writing tree inorder:");
tree.writeTree();
tree.reverseTreeOrder();
System.out.println("Writing reversed tree inorder:");
tree.writeTree();
int size=tree.sizeOfTree();
System.out.println("Number of nodes in tree is "+size+".");
boolean found = tree.containsData("Ivana");
System.out.println("Searched element is found: "+found);
}
}
Much appreciate any help provided.
You create an empty TreeNode in your constructor and make it the root of the tree:
public BinaryTree() {
TreeNode node = new TreeNode("");
root=node;
}
Later, in your insert method, your if (this.root==null) condition is always false, so you don't assign the first inserted node to the root.
Just remove it:
public BinaryTree() {
}
I have a big task to do as an exercise for Data Structures and algorithms, and part of it is to modify this tree data structure to print the tree in an alphabetical order.I won't post the whole task because it is huge. Im stuck on the last part which asks me to modify the given tree Data Structure to print the tree in an alphabetical order. I am stuck on it for couple of days and simple don't have any idea how to do it. Any help would be appriciated, thanks. My opinion is that i have to somehow modify the printTreeRecursive() method.
For example the current data structure will print a tree like this:
c: d c b a
(The first added child is printed last).
Where c: is the root and d c b a are his children
But im supposed to modify it to look like this:
c: a b c d
Here is the data structure:
public class SLLTree<E> implements Tree<E> {
// SLLNode is the implementation of the Node interface
class SLLNode<P> implements Node<P> {
// Holds the links to the needed nodes
SLLNode<P> parent, sibling, firstChild;
// Hold the data
P element;
public SLLNode(P o) {
element = o;
parent = sibling = firstChild = null;
}
public P getElement() {
return element;
}
public void setElement(P o) {
element = o;
}
}
protected SLLNode<E> root;
public SLLTree() {
root = null;
}
public Node<E> root() {
return root;
}
public Tree.Node<E> parent(Tree.Node<E> node) {
return ((SLLNode<E>) node).parent;
}
public int childCount(Tree.Node<E> node) {
SLLNode<E> tmp = ((SLLNode<E>) node).firstChild;
int num = 0;
while (tmp != null) {
tmp = tmp.sibling;
num++;
}
return num;
}
public void makeRoot(E elem) {
root = new SLLNode<E>(elem);
}
public Node<E> addChild(Node<E> node, E elem) {
SLLNode<E> tmp = new SLLNode<E>(elem);
SLLNode<E> curr = (SLLNode<E>) node;
tmp.sibling = curr.firstChild;
curr.firstChild = tmp;
tmp.parent = curr;
return tmp;
}
public void remove(Tree.Node<E> node) {
SLLNode<E> curr = (SLLNode<E>) node;
if (curr.parent != null) {
if (curr.parent.firstChild == curr) {
// The node is the first child of its parent
// Reconnect the parent to the next sibling
curr.parent.firstChild = curr.sibling;
} else {
// The node is not the first child of its parent
// Start from the first and search the node in the sibling list
// and remove it
SLLNode<E> tmp = curr.parent.firstChild;
while (tmp.sibling != curr) {
tmp = tmp.sibling;
}
tmp.sibling = curr.sibling;
}
} else {
root = null;
}
}
class SLLTreeIterator<T> implements Iterator<T> {
SLLNode<T> start, current;
public SLLTreeIterator(SLLNode<T> node) {
start = node;
current = node;
}
public boolean hasNext() {
return (current != null);
}
public T next() throws NoSuchElementException {
if (current != null) {
SLLNode<T> tmp = current;
current = current.sibling;
return tmp.getElement();
} else {
throw new NoSuchElementException();
}
}
public void remove() {
if (current != null) {
current = current.sibling;
}
}
}
public Iterator<E> children(Tree.Node<E> node) {
return new SLLTreeIterator<E>(((SLLNode<E>) node).firstChild);
}
void printTreeRecursive(Node<E> node, int level) {
if (node == null)
return;
int i;
SLLNode<E> tmp;
for (i = 0; i < level; i++)
System.out.print(" ");
System.out.println(node.getElement().toString());
tmp = ((SLLNode<E>) node).firstChild;
while (tmp != null) {
printTreeRecursive(tmp, level + 1);
tmp = tmp.sibling;
}
}
public void printTree() {
printTreeRecursive(root, 0);
}
public int countMaxChildren() {
return countMaxChildrenRecursive(root);
}
int countMaxChildrenRecursive(SLLNode<E> node) {
int t = childCount(node);
SLLNode<E> tmp = node.firstChild;
while (tmp != null) {
t = Math.max(t, countMaxChildrenRecursive(tmp));
tmp = tmp.sibling;
}
return t;
}
}
public interface Tree<E> {
// //////////Accessors ////////////
public Tree.Node<E> root();
public Tree.Node<E> parent(Tree.Node<E> node);
public int childCount(Tree.Node<E> node);
// //////////Transformers ////////////
public void makeRoot(E elem);
public Tree.Node<E> addChild(Tree.Node<E> node, E elem);
public void remove(Tree.Node<E> node);
// //////////Iterator ////////////
public Iterator<E> children(Tree.Node<E> node);
// //////Inner interface for tree nodes ////////
public interface Node<E> {
public E getElement();
public void setElement(E elem);
}
}
public class SLLTreeTest {
public static void main(String[] args) {
Tree.Node<String> a, b, c, d;
SLLTree<String> t = new SLLTree<String>();
t.makeRoot("C:");
a = t.addChild(t.root, "Program files");
b = t.addChild(a, "CodeBlocks");
c = t.addChild(b, "codeblocks.dll");
c = t.addChild(b, "codeblocks.exe");
b = t.addChild(a, "Nodepad++");
c = t.addChild(b, "langs.xml");
d = c;
c = t.addChild(b, "readme.txt");
c = t.addChild(b, "notepad++.exe");
a = t.addChild(t.root, "Users");
b = t.addChild(a, "Darko");
c = t.addChild(b, "Desktop");
c = t.addChild(b, "Downloads");
c = t.addChild(b, "My Documents");
c = t.addChild(b, "My Pictures");
b = t.addChild(a, "Public");
a = t.addChild(t.root, "Windows");
b = t.addChild(a, "Media");
t.printTree();
t.remove(d);
t.printTree();
System.out.println("The maximum number of children is "
+ t.countMaxChildren());
}
}
As I see, my initial suggestion is good-enough for the asker and other commenters as well. So, as this is a studying task, I will not write code as an answer (I would take all the fun, wouldn't I?). I will share some important checkpoints to reach in the thought process, which, if reached should lead to the solution:
we need a Collection
we need to use a breadth-first traversing (printTreeRecursive is a good example)
we need to look at the while cycle of printTreeRecursive, as it is key to reach a traversing
whenever we reach a node, we should insert sort the node into the collection
after the traversing, we iterate the Collection and print out its elements
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.
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
Just split each path by its delimiter and then add them to a tree structure one by one.
i.e. if 'x1' does not exist create this node, if it does exist go to it and check if there is a child 'x2' and so on...
I'd make the tree one string at a time.
Make an empty tree (which has a root node - I assume there could be a path like "x7/x8/x9").
Take the first string, add x1 to the root node, then x2 to x1, then x3 to x2.
Take the second string, see that x1 and x2 are already there, add x4 to x2.
Do this for every path you have.
Create an Object Node which contains a parent (Node) and a List of children (Node).
First split the string using ",". For every splitted string you split the string using "/".
Search for the first node identifier (e.g x1) in the root list.
If you can find it, use the node to find the next node identifier (e.g. x2).
If you can not find a node, add the node to the last node you was able to find in the existing lists.
After you have created the list structure, you can print the list to the screen. I would make it recursive.
NOT TESTED, just an animation
public void print(List nodes, int deep) {
if (nodes == null || nodes.isEmpty()) {
return;
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < deep; i++) {
buffer.append("---");
}
for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
Node node = (Node)iterator.next();
System.out.println(buffer.toString() + " " + node.getIdentifier());
print(node.getChildren(), deep + 1);
}
}
public class Menu {
private String path;
private List<Menu> children;
public Menu(String path) {
this.path = path;
children = new ArrayList<>();
}
public void addChild(Menu child) {
children.add(child);
}
public List<Menu> getChildren() {
return children;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Menu getChild(String data) {
for (Menu n : children)
if (n.path.equals(data)) {return n;}
return null;
}
}
Tree builder class:
public class MenuTree {
private Menu root;
public MenuTree() {
root = new Menu("");
}
public void add(String str) {
Menu current = root;
StringTokenizer s = new StringTokenizer(str, "/");
while (s.hasMoreElements()) {
str = (String) s.nextElement();
Menu child = current.getChild(str);
if (child == null) {
current.addChild(new Menu(str));
child = current.getChild(str);
}
current = child;
}
}
public JSONObject toJSON() {
try {
return new JSONObject(new ObjectMapper().writeValueAsString(this.root));
} catch (JsonProcessingException e) {
return null;
}
}
}
Usage:
String slist[] = new String[]{
"mnt/sdcard/folder1/a/b/file1.file",
"mnt/sdcard/folder1/a/b/file2.file",
"D/a/b/c.file",
};
MenuTree t = new MenuTree();
for (String s : slist) {
t.add(s);
}
System.out.println(t.toJSON().toString());
JSONObject result:
{"path":"","children":[{"path":"mnt","children":[{"path":"sdcard","children":[{"path":"folder1","children":[{"path":"a","children":[{"path":"b","children":[{"path":"file1.file","children":[]},{"path":"file2.file","children":[]}]}]}]}]}]},{"path":"D","children":[{"path":"a","children":[{"path":"b","children":[{"path":"c.file","children":[]}]}]}]}]}
Make your tree for every string in array.
Just split path for '/' , check whether the node exists in your tree or not, if it exists then move on... otherwise create a new node and add this node in childrens of parent node.
Iterate using recursion.
Following is model for tree's node.
Class Node{
string name;
List<Node> childrens;
Node(string name){
this.name = name;
this.childrens = new List<Node>();
}
}
This is way how I am doing tree from path (folders) structure. Maybe should help someone with basic logic.
Node:
public class Node {
private String path;
private List<Node> children;
public Node(String path) {
this.path = path;
children = new ArrayList<>();
}
public String getName() {
return getName(path);
}
private String getName(String path) {
String[] split = path.split("\\\\");
return split[split.length - 1];
}
public void addChild(Node child) {
children.add(child);
}
public List<Node> getChildren() {
return children;
}
public String getPath() {
return path;
}
}
FilesTree:
public class FilesTree {
private static final Logger log = Logger.getLogger(FilesTree.class.getName());
private FilesTree() {}
private static void createTree(Node root, List<String> paths) {
for (String path : paths) {
addNode(root, Arrays.asList(path.split("\\\\")), "");
}
}
private static void addNode(Node node, List<String> path, String nodePath) {
if (!path.isEmpty()) {
nodePath = nodePath.equals("") ? path.get(0) : String.format("%s\\%s", nodePath, path.get(0));
}
if (node.getChildren().isEmpty() && path.size() == 1) {
node.addChild(new Node(nodePath));
} else if (!node.getChildren().isEmpty()) {
for (Node actual : node.getChildren()) {
if (actual.getName().equals(path.get(0))) {
addNode(actual, path.subList(1, path.size()), nodePath);
return;
}
}
node.addChild(new Node(nodePath));
} else {
log.info("Without children but with size: " + path.size());
}
}
}