I was trying to implement a class Node to build a tree of Nodes. Basically, each Node can have children, so if I specify multiple nodes I can build a tree out of it. As an example:
node1 (the root) has node2 and node3 as children node2 has node4 and node5 as children
The problem I am having problems to solve is to build this tree and find all children of a given element (in this case node1 would have 4 children, since it has node2 and node3 in the first place, and node2 has 2 children, so in total 4). Does anyone have any suggestion?
EDIT:
package ex1; import java.sql.Array; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class Node { private String name; private String description; private ArrayList<Node> children = new ArrayList<>(); Node(String name, String description){ this.name = name; this.description = description; } private void setName(String name){ this.name = name; } private void setDescription(String description) { this.description = description; } public void addChildren(Node child) { this.children.add(child); } public String getName() { return this.name; } public String getDescription() { return this.description; } public boolean hasDescription() { return !description.isEmpty(); } public Collection<Node> getChildren() { return this.children; } /* public Node findNodeByName(String name, Node t) { if (t.getName().equals(name)) return t; t.getChildren().forEach(node -> node.findNodeByName(name,node)); return null; }*/ public Node findNodeByName(String name, Node t){ if(t.getName().equals(name)){ return t; } else if (t.getChildren().size() != 0){ for(Node c: children){ Node ret = c.findNodeByName(name,c); if(ret != null){ return ret; } } } return null; } // IMPORTANT: Don't change this method! private String toString(int indentNo) { String indent = "t".repeat(indentNo); StringBuffer b = new StringBuffer(); b.append(indent); b.append(getClass().getSimpleName() + " '" + getName() + "' "); if (hasDescription()) { b.append("(description: " + getDescription() + ")"); } b.append("n"); for (Node node : getChildren()) { b.append(node.toString(indentNo + 1)); } return b.toString(); } @Override public String toString() { return toString(0); } }
Method where I make use of the class:
Path path = Path.of(pathname); String fileContent = null; try { fileContent = Files.readString(path); } catch (IOException e) { throw new RuntimeException(e); } List<String> lines = new ArrayList<>(Arrays.asList(fileContent.split("n"))); String[] firstLine = lines.get(0).split(","); Node parentNode = new Node(firstLine[0], firstLine[1]); lines.remove(0); /* This was just to test findNodeByName for(String line: lines) { String[] params = line.split(","); System.out.println(params[2] + ": " + (parentNode.findNodeByName(params[2], parentNode) != null)); }*/ //Now we read all remaining data Node tmpNode; for(String line: lines) { String[] params = line.split(","); if (parentNode.findNodeByName(params[2])==null || parentNode.findNodeByName(params[0])!=null) //if parent was not found or name already exists throw new IOException(); tmpNode = parentNode.findNodeByName(params[2]); tmpNode.addChildren(new Node(params[0],params[1])); }
CSV file I am getting the data from:
uni,"This is my university folder", firstyear,,uni secondyear,,uni analysis,"folder for the analysis course",firstyear ai,"folder for the artificial intelligence course",secondyear db,"folder for the database course",firstyear
Advertisement
Answer
Here is some sample code that could help (explanation below):
Main class:
class Main { public static void main(String[] args) { Node v1 = new Node(1); Node v2 = new Node(2); Node v3 = new Node(3); Node v4 = new Node(4); Node v5 = new Node(5); v1.addChild(v2); v1.addChild(v3); v2.addChild(v4); v2.addChild(v5); v1.printChildren(); } }
Node class:
import java.util.*; class Node{ private int val; private ArrayList<Node> children = new ArrayList<Node>(); public Node(int v){ val = v; } public void addChild (Node c){ children.add(c); } public void printChildren(){ if (children.size() != 0){ System.out.print("Children of Node " + getValue() + ": "); for(Node c: children){ System.out.print("Node " + c.getValue() + " "); } System.out.println(); for(Node c: children){ c.printChildren(); } } } public int getValue(){ return val; } }
Output:
Children of Node 1: Node 2 Node 3 Children of Node 2: Node 4 Node 5
Ok so in our node class, let’s say each node will have an integer value, val
. That is our first private instance variable. Second, each node will have a list of children nodes, children
.
When we first declare our nodes, they will have integer values, as shown in our constructor.
After we define our nodes, we can add some nodes as children to other nodes (v2 and v3 are children to v1, and v4 and v5 are children to v2).
Now we need to print them. We will use a recursive approach for this. If the node we are printing the children of has children (the length of our children ArrayList is nonzero), then we will first iterate through that list, and print out the children of our current node. Afterwards, we again iterate through each child and use the same method (recursion) to print out the children of that node.
I hope this helped! Please let me know if you need any further help or clarification 🙂
EDIT:
Added a getName()
method:
public String getName(){ return "Node" + getValue(); }
Added the requested method:
public Node findChildNodeByValue(int v){ if(getValue() == v){ System.out.println(getName() + " has the value"); return new Node(getValue()); } else if (children.size() != 0){ for(Node c: children){ Node ret = c.findChildNodeByValue(v); if(ret != null){ return ret; } } } return null; }
Quick Explanation: Very similar to the original method, we use a recursive approach to iterate through each nodes’ children: Once we reach a node with no more children, we return null. Once we reach the node with the given value, we return a copy of that node, which will be sent back to wherever the function was called..
Also edited main method:
Node v1 = new Node(1); Node v2 = new Node(2); Node v3 = new Node(3); Node v4 = new Node(4); Node v5 = new Node(5); v1.addChild(v2); v1.addChild(v3); v2.addChild(v4); v2.addChild(v5); // v1.printChildren(); Node valNode = v1.findChildNodeByValue(5); System.out.println(valNode.getName());
Output:
Node5 has the value Node5
SECOND EDIT:
Change the method to look like this:
public Node findNodeByName(String name){ if(getName().equals(name)){ Node t = new Node(getName(), getDescription()); return t; } else if (getChildren().size() != 0){ for(Node c: children){ Node ret = c.findNodeByName(name); if(ret != null){ return ret; } } } return null; }
The main method should look like this:
Node v1 = new Node("a","aa"); Node v2 = new Node("b","bb"); Node v3 = new Node("c","cc"); Node v4 = new Node("d","dd"); Node v5 = new Node("e","ee"); v1.addChildren(v2); v1.addChildren(v3); v2.addChildren(v4); v2.addChildren(v5); System.out.println(v1.findNodeByName("e"));
Output:
Node 'e' (description: ee)
THIRD EDIT:
Added a new method:
public void setChildren(ArrayList<Node> c){ children = c; }
Edited method:
public Node findNodeByName(String name){ if(getName().equals(name)){ Node t = new Node(getName(), getDescription()); t.setChildren(getChildren()); return t; } else if (getChildren().size() != 0){ for(Node c: children){ Node ret = c.findNodeByName(name); if(ret != null){ return ret; } } } return null; }
Main Method:
Node v1 = new Node("a","aa"); Node v2 = new Node("b","bb"); Node v3 = new Node("c","cc"); Node v4 = new Node("d","dd"); Node v5 = new Node("e","ee"); Node v6 = new Node("f","ff"); v1.addChildren(v2); v1.addChildren(v3); v2.addChildren(v4); v2.addChildren(v5); v4.addChildren(v6); Node vNew = v1.findNodeByName("d"); System.out.println(vNew); System.out.println(vNew.getChildren());
Output:
Node 'd' (description: dd) Node 'f' (description: ff) [Node 'f' (description: ff) ]