Replace collections in Tree implementatnion - java

I have a Tree implementation but i want change ArrayList to simply array, i don't want use collection in java i just want use array but i don't know how i can replace ArrayList to simply array.
There is a code:
public class TreeNode {
private String data = null;
private List<TreeNode> children = new ArrayList<>();
int topSize;// I added it, since i know how is the size of Tree
private TreeNode[] children2 = new TreeNode[topSize];//I added it
private TreeNode parent = null;
public TreeNode(String data) {
this.data = data;
}
int i = 0;//I added it
public void addChild(TreeNode child) {
child.setParent(this);
this.children.add(child);
this.children2[i++] = child;//I added it
}
public void addChild(String data) {
TreeNode newChild = new TreeNode(data);
newChild.setParent(this);
children.add(newChild);
children2[i] = newChild;// I added it
}
public void addChildren(List<TreeNode> children) {
for (TreeNode t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<TreeNode> getChildren() {
return children;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
private void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getParent() {
return parent;
}
public static void main(String[] args) {
TreeNode root = new TreeNode("Root");
TreeNode child1 = new TreeNode("Child1");
child1.addChild("Grandchild1");
child1.addChild("Grandchild2");
TreeNode child2 = new TreeNode("Child2");
child2.addChild("Grandchild3");
root.addChild(child1);
root.addChild(child2);
root.addChild("Child3");
root.addChildren(Arrays.asList(
new TreeNode("Child4"),
new TreeNode("Child5"),
new TreeNode("Child6")
));
TreeNode mainRoot = new TreeNode("MainRoot");
mainRoot.addChildren(Arrays.asList(root));
for (TreeNode node : root.getChildren()) {
System.out.println(node.getData());
}
}
}
I create TreeNode[] children2 array and add int topSize, since i know what size tree will be.But it doesn't work correctly. I want Tree without collections from java.java.lang.ArrayIndexOutOfBoundsException: 0 in children2[i] = newChild;

The topSize variable is never assigned in our code, so it has the default value: 0. This means that children2 is an empty array. That's why you get an ArrayIndexOutOfBoundsException while putting something into it.
Try to initialize topSize with some value, for example:
int topSize = 10;
After this modification, your program runs with no exceptions.

Related

Problem with accessing reference in ArrayList

Unable to add new element (node) to ArrayList
Node N = new Node(5,"Sandeep");
Node N1 = new Node(5,"qwert");
In below line I am getting null pointer exception
N.children.add(N1)
Code:
class Node {
public int val;
public String data;
public ArrayList<Node> children;
public Node(int val, String data) {
this.val = val;
this.data = data;
ArrayList<Node> children = new ArrayList<Node>();
}
}
public class Nary {
public static void main(String[] args) {
// ArrayList<Node> children = new ArrayList<Node>();
Node N = new Node(5,"Sandeep");
Node N1 = new Node(5,"qwert");
N.children.add(N1);
}
}
Change this in your code
class Node {
public int val;
public String data;
public ArrayList<Node> children;
public Node(int val, String data) {
this.val = val;
this.data = data;
this.children = new ArrayList<Node>();
}
}
In Node constructor you are creating new local attribute of children
If you change below in constructor its will works fine
this.children = new ArrayList();

Please review these code. It doesn't work like I expected [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
The code didn't work as I think.I have tried to recode but still can't get the result I hope for. Here's the code:
public class Node<T> {
private List<Node<T>> children = new ArrayList<Node<T>>();
private Node<T> parent = null;
private T data = null;
private String a = "";
public Node(T data) { //used to create parent
this.data = data;
}
public Node(T data, Node<T> parent) {
this.parent = parent;
Node<T> child = new Node<T>(data);
this.parent.children.add(child);
}
public Node<T> getParent(Node<T> child){
return child.parent;
}
public List<Node<T>> getChildren() {
return children;
}
public int getSize(){
return children.size();
}
public String toString(){
for(int i=0; i<children.size();i++){
a = a + parent.children.get(i).getData()+ ",";
}
return a ;
}
public T getData() {
return data;
}
}
import java.util.List;
public class main {
public static void main(String[] args) {
Node<String> parentNode = new Node<String>("Parent");
Node<String> childNode1 = new Node<String>("Child 1", parentNode);
Node<String> childNode2 = new Node<String>("Child 2", parentNode);
List<Node<String>> ChildrenOfParents = parentNode.getChildren();
System.out.println(ChildrenOfParents.size());
System.out.println(ChildrenOfParents.toString());
}
}
After these lines of code, I wonder why ChildrenOfParents.toString() will not print out the children? Those child already added into the ChildrenOfParents right? I'm still new in java. Please guide me through the code. I wish to make a family tree without restriction of Family members(For example, father can have many sons instead of just 2 if follow binary tree). Thanks.
PS: Thanks for the answer that "this.parent.children.add(this)" makes the program works. But I wonder why "this.parent.children.add(child)" at line 12 doesn't work when the constructor with parameter is called? Isn't the parent's children variable will add the child into the list?
You need add child into parent object in the second constructor:
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) { //used to create parent
this.data = data;
}
public Node(T data, Node<T> parent) {
this.parent = parent;
this.data = data;
this.parent.children.add(this);
}
public Node<T> getParent(Node<T> child) {
return child.parent;
}
public List<Node<T>> getChildren() {
return children;
}
public int getSize() {
return children.size();
}
public String toString() {
String a = "";
for (int i = 0; i < children.size(); i++) {
a = a + children.get(i).getData() + ",";
}
return a;
}
public T getData() {
return data;
}
}
public class NodeApp {
public static void main(String[] args) {
Node<String> parentNode = new Node<String>("Parent");
Node<String> childNode1 = new Node<String>("Child 1", parentNode);
Node<String> childNode2 = new Node<String>("Child 2", parentNode);
System.out.println(parentNode.getSize());
System.out.println(parentNode.toString());
}
}

Get the parent path of Node in a tree

I am using the following code to convert a flat structure like:
test/test2/test3
test/test5/test2
test/test7/test5/test4
test/test7/test5/test9
into a tree like:
test
| | |
test2 test5 test7
| | |
test3 test2 test5
| |
test4 test9
The code:
import java.util.*;
class Tree
{
class Node
{
String data;
ArrayList<Node> children;
public Node(String data)
{
this.data = data;
children = new ArrayList<Node>();
}
public ArrayList<Node> getChildren()
{
return children;
}
public Node getChild(String data)
{
for(Node n : children)
if(n.data.equals(data))
return n;
return null;
}
}
private Node root;
public Tree()
{
root = new Node("");
}
public boolean isEmpty()
{
return root==null;
}
public void add(String str)
{
Node current = root;
StringTokenizer s = new StringTokenizer(str, "/");
while(s.hasMoreElements())
{
str = (String)s.nextElement();
Node child = current.getChild(str);
if(child==null)
{
current.children.add(new Node(str));
child = current.getChild(str);
}
current = child;
}
}
public void get()
{
return root;
}
}
I use the "add" function to split the above flat paths to a tree and it works nicely and I am able to navigate forward. Though, I want to be able to navigate to the Node with a given path and also when I navigate to some Node, I want to be able to trace it to the root element. For example, if I navigate from test -> test2 -> test3, I want to get the path from the root like test/test2/test3.
I am new to Trees and the topic is confusing me a bit, your help is highly appreciated.
Edit: Added a visual representation.
public class Tree {
private final Node root = new Node(null, null);
public boolean isEmpty() {
return root.children.isEmpty();
}
public void add(String path) {
Node parent = root;
for (String data : path.split("/")) {
Node node = parent.getChild(data);
if (node == null)
parent.children.add(node = new Node(data, parent));
parent = node;
}
}
public Node get(String path) {
Node parent = root;
for (String data : path.split("/")) {
Node node = parent.getChild(data);
if (node == null)
return null;
parent = node;
}
return parent;
}
public static final class Node {
private final String data;
private final Node parent;
private final List<Node> children = new LinkedList<>();
public Node(String data, Node parent) {
this.data = data;
this.parent = parent;
}
public List<Node> getChildren() {
return Collections.unmodifiableList(children);
}
public Node getChild(String data) {
for (Node node : children)
if (node.data.equals(data))
return node;
return null;
}
public String getPath() {
Deque<String> nodes = new LinkedList<>();
Node node = this;
while (node.parent != null) {
nodes.addFirst(node.data);
node = node.parent;
}
return String.join("/", nodes);
}
#Override
public String toString() {
return data;
}
}
public static void main(String... args) {
Tree tree = new Tree();
tree.add("test/test2/test3");
tree.add("test/test5/test2");
tree.add("test/test7/test5/test4");
tree.add("test/test7/test5/test9");
Node node = tree.get("test/test7/test5/test9");
String path = node.getPath();
}
}
A simple way is to keep track of the parent node, then just follow the parents up the tree from the child:
Node currentNode = ...
ArrayList<Node> path = new ArrayList<>();
while(currentNode != null){
path.add(currentNode);
currentNode = currentNode.getParent();
}
Collections.reverse(path);
So your Node class would need a new constructor:
class Node {
String data;
ArrayList<Node> children;
Node parent;
Node(Node parent, String data){
// ...
}
// ...
// Null if this is the root, else returns the parent node
public Node getParent(){ return parent; }
}

I have a data where 1100 is parent and 1101,1102,1103 are the child nodes. How to implement this in Java?

I have a data where 1100 is parent and 1101,1102,1103 are child nodes. How can I implement this thing in java what concept I use?
It's structure is like
1100
1101
1102
1103
write a data structure for your nodes of tree:
public static class Node {
private int value;
private Node parent;
private List<Node> children;
}
and add some functionality like addChild, removeChild, setParent, getValue and ... as you wish.
You need a Node class that has references to its children which are specified in a List<Node>.
public class Node {
private int data;
private List<Node> children;
public Node(int data) {
this.data = data;
this.children = new ArrayList<>();
}
public void addChild(Node node) {
this.children.add(node);
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public List<Node> getChildren() { //TODO: smarter way of encapsulation
return this.children;
}
}
public class Main {
public static void main(String[] args) {
Node mainNode = new Node(1100);
mainNode.addChild(new Node(1101));
mainNode.addChild(new Node(1102));
mainNode.addChild(new Node(1103));
}
}
If you need to know the parent for each child node, then you just need to add the Parent:
public class Node {
private int data;
private List<Node> children;
private Node parent;
public void setParent(Node node) { this.parent = node; }
public Node getParent() { return parent; }
and in addChild method
public void addChild(Node node) {
this.children.add(node);
node.setParent(this);
}
In which case you really shouldn't have the getChildren() method exposed like that.

java.util.ConcurrentModificationException while merge node in a tree structure

I want to merge the node which has the same name, and add their children together.
But I got a java.util.ConcurrentModificationException exception:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at test.Test.mergeNode(Test.java:60)
at test.Test.main(Test.java:43)
Following is the source.Could someone give any hints? Any suggestions will be welcomed.
public class Test {
public static void main(String[] args) throws Exception {
TreeLayoutNode root = new TreeLayoutNode();
root.setName("Production");
TreeLayoutNode node1 = new TreeLayoutNode();
node1.setName("node1");
TreeLayoutNode node2 = new TreeLayoutNode();
node2.setName("node1");
TreeLayoutNode child1 = new TreeLayoutNode();
child1.setName("child1");
TreeLayoutNode child2 = new TreeLayoutNode();
child2.setName("child2");
TreeLayoutNode child3 = new TreeLayoutNode();
child3.setName("child3");
root.addChildNode(node1);
root.addChildNode(node2);
node1.addChildNode(child1);
node1.addChildNode(child2);
node2.addChildNode(child1);
node2.addChildNode(child3);
HashMap<String, TreeLayoutNode> nodeMap = Maps.newHashMap();
mergeNode(root, nodeMap);
}
/**
*
* #param node
*/
private static void mergeNode(TreeLayoutNode node, HashMap<String, TreeLayoutNode> nodeMap) {
List<TreeLayoutNode> children = node.getChildren();
if(CollectionUtils.isEmpty(children)){
return;
}
Iterator<TreeLayoutNode> it = children.iterator();
while(it.hasNext()){
TreeLayoutNode child = it.next();
if(nodeMap.containsKey(child.getName())){
TreeLayoutNode duplicate = nodeMap.get(child.getName());
List<TreeLayoutNode> childrenOfChild = child.getChildren();
if(CollectionUtils.isNotEmpty(childrenOfChild)){
for(TreeLayoutNode single: childrenOfChild){
duplicate.addChildNode(single);
}
node.removeChildNode(child);
mergeNode(duplicate, nodeMap);
}
}else{
nodeMap.put(child.getName(), child);
}
}
}
}
public class TreeLayoutNode {
private String name;
private String parent;
private Long capacity;
private List<Proportion> proportions;
private List<TreeLayoutNode> children;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
public Long getCapacity() {
return capacity;
}
public void setCapacity(Long capacity) {
this.capacity = capacity;
}
public List<Proportion> getProportions() {
return proportions;
}
public void setProportions(List<Proportion> proportions) {
this.proportions = proportions;
}
public List<TreeLayoutNode> getChildren() {
return children;
}
public void setChildren(List<TreeLayoutNode> children) {
this.children = children;
}
public void addChildNode(TreeLayoutNode child) {
if (children == null) {
children = Lists.newArrayList();
}
child.setParent(this.getName());
children.add(child);
}
public void removeChildNode(TreeLayoutNode child){
children.remove(child);
}
public void addProportion(Proportion proportion) {
if (proportions == null) {
proportions = Lists.newArrayList();
}
proportions.add(proportion);
}
public int hashCode() {
return name == null ? 0: name.hashCode();
}
public boolean equals(Object o) {
if (o instanceof TreeLayoutNode) {
TreeLayoutNode target = (TreeLayoutNode) o;
if (this.name == null) {
return target.getName() == null;
} else {
return this.name.equals(target.getName());
}
} else {
return false;
}
}
}
Iterator<TreeLayoutNode> it = children.iterator();
while(it.hasNext()){
TreeLayoutNode child = it.next();
if(nodeMap.containsKey(child.getName())){
TreeLayoutNode duplicate = nodeMap.get(child.getName());
List<TreeLayoutNode> childrenOfChild = child.getChildren();
if(CollectionUtils.isNotEmpty(childrenOfChild)){
for(TreeLayoutNode single: childrenOfChild){
duplicate.addChildNode(single);
}
node.removeChildNode(child);
mergeNode(duplicate, nodeMap);
}
}else{
nodeMap.put(child.getName(), child);
}
}
This loop is the problem in your code. When you are using an Iterator, you can not modify the underlying Collection. In this case you are iterating over 'children' in this loop, and you are removing items from the underlying list when you call 'node.removeChildNode( child )'.
A solution is to clone the 'children' list before you iterator over it.
List< TreeLayoutNode > children = node.getChildren().clone();
This means you are no longer iterating over the list that is being edited in the later on in the method.
You could also create another List to store children nodes to be removed after you are done iterating over it.
List< TreeLayoutNode > removedChildren = new LinkedList< >();
// Iterate over the elements, adding children to be removed to removedChildren
for( TreeLayoutNode child : removedChildren ) {
node.removeChildNode( child );
}
Finally you could use 'it.remove()' to remove the element from the underlying Collection. This method has the disadvantage of breaking encapsulation.
// node.removeChildNode( child )
it.remove();

Categories