I need to create a tree structure similar as the attached image in Java. I\'ve found some questions related to this one but I haven\'t found a convincing and well explained
Since @Jonathan's answer still consisted of some bugs, I made an improved version. I overwrote the toString()
method for debugging purposes, be sure to change it accordingly to your data.
import java.util.ArrayList;
import java.util.List;
/**
* Provides an easy way to create a parent-->child tree while preserving their depth/history.
* Original Author: Jonathan, https://stackoverflow.com/a/22419453/14720622
*/
public class TreeNode<T> {
private final List<TreeNode<T>> children;
private TreeNode<T> parent;
private T data;
private int depth;
public TreeNode(T data) {
// a fresh node, without a parent reference
this.children = new ArrayList<>();
this.parent = null;
this.data = data;
this.depth = 0; // 0 is the base level (only the root should be on there)
}
public TreeNode(T data, TreeNode<T> parent) {
// new node with a given parent
this.children = new ArrayList<>();
this.data = data;
this.parent = parent;
this.depth = (parent.getDepth() + 1);
parent.addChild(this);
}
public int getDepth() {
return this.depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
public List<TreeNode<T>> getChildren() {
return children;
}
public void setParent(TreeNode<T> parent) {
this.setDepth(parent.getDepth() + 1);
parent.addChild(this);
this.parent = parent;
}
public TreeNode<T> getParent() {
return this.parent;
}
public void addChild(T data) {
TreeNode<T> child = new TreeNode<>(data);
this.children.add(child);
}
public void addChild(TreeNode<T> child) {
this.children.add(child);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRootNode() {
return (this.parent == null);
}
public boolean isLeafNode() {
return (this.children.size() == 0);
}
public void removeParent() {
this.parent = null;
}
@Override
public String toString() {
String out = "";
out += "Node: " + this.getData().toString() + " | Depth: " + this.depth + " | Parent: " + (this.getParent() == null ? "None" : this.parent.getData().toString()) + " | Children: " + (this.getChildren().size() == 0 ? "None" : "");
for(TreeNode<T> child : this.getChildren()) {
out += "\n\t" + child.getData().toString() + " | Parent: " + (child.getParent() == null ? "None" : child.getParent().getData());
}
return out;
}
}
And for the visualization:
import model.TreeNode;
/**
* Entrypoint
*/
public class Main {
public static void main(String[] args) {
TreeNode<String> rootNode = new TreeNode<>("Root");
TreeNode<String> firstNode = new TreeNode<>("Child 1 (under Root)", rootNode);
TreeNode<String> secondNode = new TreeNode<>("Child 2 (under Root)", rootNode);
TreeNode<String> thirdNode = new TreeNode<>("Child 3 (under Child 2)", secondNode);
TreeNode<String> fourthNode = new TreeNode<>("Child 4 (under Child 3)", thirdNode);
TreeNode<String> fifthNode = new TreeNode<>("Child 5 (under Root, but with a later call)");
fifthNode.setParent(rootNode);
System.out.println(rootNode.toString());
System.out.println(firstNode.toString());
System.out.println(secondNode.toString());
System.out.println(thirdNode.toString());
System.out.println(fourthNode.toString());
System.out.println(fifthNode.toString());
System.out.println("Is rootNode a root node? - " + rootNode.isRootNode());
System.out.println("Is firstNode a root node? - " + firstNode.isRootNode());
System.out.println("Is thirdNode a leaf node? - " + thirdNode.isLeafNode());
System.out.println("Is fifthNode a leaf node? - " + fifthNode.isLeafNode());
}
}
Example output:
Node: Root | Depth: 0 | Parent: None | Children:
Child 1 (under Root) | Parent: Root
Child 2 (under Root) | Parent: Root
Child 5 (under Root, but with a later call) | Parent: Root
Node: Child 1 (under Root) | Depth: 1 | Parent: Root | Children: None
Node: Child 2 (under Root) | Depth: 1 | Parent: Root | Children:
Child 3 (under Child 2) | Parent: Child 2 (under Root)
Node: Child 3 (under Child 2) | Depth: 2 | Parent: Child 2 (under Root) | Children:
Child 4 (under Child 3) | Parent: Child 3 (under Child 2)
Node: Child 4 (under Child 3) | Depth: 3 | Parent: Child 3 (under Child 2) | Children: None
Node: Child 5 (under Root, but with a later call) | Depth: 1 | Parent: Root | Children: None
Is rootNode a root node? - true
Is firstNode a root node? - false
Is thirdNode a leaf node? - false
Is fifthNode a leaf node? - true
import java.util.ArrayList;
import java.util.List;
public class Node<T> {
private List<Node<T>> children = new ArrayList<Node<T>>();
private Node<T> parent = null;
private T data = null;
public Node(T data) {
this.data = data;
}
public Node(T data, Node<T> parent) {
this.data = data;
this.parent = parent;
}
public List<Node<T>> getChildren() {
return children;
}
public void setParent(Node<T> parent) {
parent.addChild(this);
this.parent = parent;
}
public void addChild(T data) {
Node<T> child = new Node<T>(data);
child.setParent(this);
this.children.add(child);
}
public void addChild(Node<T> child) {
child.setParent(this);
this.children.add(child);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRoot() {
return (this.parent == null);
}
public boolean isLeaf() {
return this.children.size == 0;
}
public void removeParent() {
this.parent = null;
}
}
Example:
import java.util.List;
Node<String> parentNode = new Node<String>("Parent");
Node<String> childNode1 = new Node<String>("Child 1", parentNode);
Node<String> childNode2 = new Node<String>("Child 2");
childNode2.setParent(parentNode);
Node<String> grandchildNode = new Node<String>("Grandchild of parentNode. Child of childNode1", childNode1);
List<Node<String>> childrenNodes = parentNode.getChildren();