Tree Comparison Algorithm in Java - java

I am looking for an algorithm to compare two trees.
I have this class in Java
public class TreeNodeDSP {
TreeNodeDSP parent;
List<TreeNodeDSP> children;
NodeDSP value;
public TreeNodeDSP(TreeNodeDSP parent) {
this.parent = parent;
children = new ArrayList<>();
}
public TreeNodeDSP(TreeNodeDSP parent, NodeDSP value) {
this.parent = parent;
children = new ArrayList<>();
this.value = value;
}
public void addChild(TreeNodeDSP node) {
if (node != null && node.getValue() != null) {
if (children.stream().noneMatch(child -> Objects.equals(child.getValue(), node.getValue()))) {
children.add(node);
}
}
}
public TreeNodeDSP getParent() {
return parent;
}
public void cleanChildren() {
children = new ArrayList<>();
}
public int getChildrenCount() {
return children.size();
}
public TreeNodeDSP getChildrenAt(int position) {
if (children.size() > position && position > -1) {
return children.get(position);
}
return null;
}
public List<TreeNodeDSP> getChildren() {
return children;
}
public NodeDSP getValue() {
return value;
}
public boolean isLeaf() {
return children.isEmpty();
}
}
I think the code of NodeDSP class is not needed.
Now, I have an algorithm to populate my Tree (TreeNodeDSP) and facing problem performing operations based on Automatically populate Tree (calculating some conditions),
I populate manually my Tree and works.
I need to discover what is the difference in my Tree (manually Populated, and Automatically) in its nodes (internally), not only says are different Trees. When some node/leaf is different I need to print its contents.
But, I don't know how to begin with the comparison Algorithm.

Related

Deleting node from generic tree

I can't write correctly function that deletes one node from tree. If this node has children, they should move one level higher. Children of deleted element will have parent of deleted elem,ancestors will they on they places, but one level higher. How can I do it right?
import java.util.ArrayList;
import java.util.List;
public class Node<T> {
private T value;
private final List<Node<T>> listOfChildren;
private Node<T> parent;
public Node(){
super();
listOfChildren = new ArrayList<>();
}
public Node(T value){
this();
setValue(value);
}
public T getValue() {
return value;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
public List<Node<T>> getListOfChildren() {
return listOfChildren;
}
public void setValue(T value) {
this.value = value;
}
public int getNumberOfChildren() {
return listOfChildren.size();
}
public void addChildren(Node<T> child) {
parent = this;
listOfChildren.add(child);
}
public void removeChildAt(int index) {
if (index > listOfChildren.size()-1){
throw new IndexOutOfBoundsException( "This index is too big");
}
else {
Node<T> element = this.listOfChildren.get(index);
if (element.listOfChildren.size() > 0) {
// function...
}
listOfChildren.remove(index);
}
}
}
I think that writing dfs or bfs to walk through the tree is not the best way to realize this function. What is the best way to realize this function?
Children of deleted element will keep their descendants, so no walk through required
public void removeChildAt(int index) throws IndexOutOfBoundsException {
if (listOfChildren != null) {
Node<T> element = this.listOfChildren.get(index);
if (element.listOfChildren.size() > 0) {
this.listOfChildren.addAll(element.listOfChildren);
//element.listOfChildren.forEach(child -> child.setParent(this)); but you have no backward reference to parent
}
listOfChildren.remove(index);
}
else {
System.out.println("No children from this node");
}
}

Insert a node in Tree with more than 2 children per node

I have a database table with parent child relationship and any parent can have any number of children but there will only be 1 parent at the root level. Data looks like below:
TagID ParentTagID TagName
-------------------------------
1 null a
2 1 b
3 1 c
4 1 d
5 2 e
6 4 f
7 2 g
I want to fetch the records in java in a tree format. Although I can achieve this at SQL level itself using the below SQL but I want to extract the data from database as it is and perform the processing at java level so that the connection between java and SQL could be of minimum duration to avoid any latency from database side.
with cte as
(
select * from TagValue
where ParentTagID is null
union all
select s.* from TagValue s
join cte c on s.ParentTagID = c.TagID
)
select * from cte
Using Java with taking help from other useful links, I have created a tree as per below:
public class MyTreeNode<T> {
private T data = null;
private List<MyTreeNode<T>> children = new ArrayList<MyTreeNode<T>>();
private MyTreeNode<T> parent = null;
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode<T> child) {
child.setParent(this);
this.children.add(child);
}
public void addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<T>(data);
newChild.setParent(this);
children.add(newChild);
}
public void addChildren(List<MyTreeNode<T>> children) {
for (MyTreeNode<T> t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<MyTreeNode<T>> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private void setParent(MyTreeNode<T> parent) {
this.parent = parent;
}
public MyTreeNode<T> getParent() {
return parent;
}
}
While inserting objects in this tree, I can use the below code:
MyTreeNode<Integer> root = new MyTreeNode<Integer>(1);
MyTreeNode<Integer> child1 = new MyTreeNode<Integer>(2);
child1.addChild(3);
child1.addChild(4);
MyTreeNode<Integer> child2 = new MyTreeNode<Integer>(5);
child2.addChild(6);
root.addChild(child1);
root.addChild(child2);
root.addChild(7);
root.addChildren(Arrays.asList(new MyTreeNode<Integer>(8),
new MyTreeNode<Integer>(9), new MyTreeNode<Integer>(10)));
But this is a static code whereas the number of tags could be dynamic. I need a recursive solution to find a node based on ParentTag value and then insert the new tag as its child. Is there a recursive solution to do this? If there is any other out of the box data structure in Java 1.8 to perform this operation, that would also be useful.
Given a ResultSet, you would like to build your tree structure naturally, as follows:
while (... has more rows ...) {
addNode(rs.ParentTagID, rs.TagID);
You need some type of container to store your tree nodes in. You could use a List however the performance will suffer when building the tree; adding a child requires finding its parent, and a list offers no quick way to do this. A Map
however provides O(1) lookup.
The helper method addNode will keep the tree in tact: Find the parent, and add the child accordingly.
In summary the dynamic approach you are looking for is to iterate the result set, and repeatedly call addNode() passing both the parentId and childId (which is stored in the database). The root node is a special case (where parentId = null or 0) and is handled by addNode().
There was a slight modification to MyTreeNode to return the object (when adding a child); it used to be of type void.
Here is some sample code showing this approach.
public class MutipleTreeNode {
static Map<Integer, MyTreeNode<Integer>> nodeMap = new HashMap<>();
public static void main(String[] args) {
// Here you would process your result set
// Rather than simulate a result set, I just build some nodes manually
addNode(0, 1); // Root
addNode(1, 2);
addNode(1, 3);
addNode(1, 4);
addNode(2, 5);
addNode(2, 7);
addNode(4, 6);
printTree();
}
private static void printTree() {
for (MyTreeNode<Integer> node : nodeMap.values()) {
if (node.getParent() == null)
System.out.print("Root node: ");
System.out.println(node.getData()+"; children="+node.getChildren());
}
}
private static void addNode(int parentId, int childId) {
MyTreeNode<Integer> childNode, parentNode;
if (nodeMap.isEmpty())
childNode = new MyTreeNode<Integer>(childId);
else {
parentNode = nodeMap.get(parentId);
childNode = parentNode.addChild(childId);
}
nodeMap.put(childId, childNode);
}
public static class MyTreeNode<T> {
private T data = null;
private List<MyTreeNode<T>> children = new ArrayList<MyTreeNode<T>>();
private MyTreeNode<T> parent = null;
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode<T> child) {
child.setParent(this);
this.children.add(child);
}
public MyTreeNode<T> addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<T>(data);
newChild.setParent(this);
children.add(newChild);
return newChild;
}
public void addChildren(List<MyTreeNode<T>> children) {
for (MyTreeNode<T> t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<MyTreeNode<T>> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private void setParent(MyTreeNode<T> parent) {
this.parent = parent;
}
public MyTreeNode<T> getParent() {
return parent;
}
#Override
public String toString() {
return "[data=" + data + "]";
}
}
}
Creates the output:
Root node: 1; children=[[data=2], [data=3], [data=4]]
2; children=[[data=5], [data=7]]
3; children=[]
4; children=[[data=6]]
5; children=[]
6; children=[]
7; children=[]

Iterating and root find in a java tree structure

I am new in tree like structures.I have write this kind of a tree.
How to iterate over a tree ?
How to find all roots (i have a method for the main root but i want to find all roots which are inside the tree) in a tree ?
What is the correct way to use a tree structure in java - every time write your one class or using TreeMap ?
TreeNode
public class TreeNode<T> {
private T value;
private boolean hasParent;
private ArrayList<TreeNode<T>> children;
public TreeNode(T value) {
if (value == null) {
throw new IllegalArgumentException("Cannot insert null value!");
}
this.value = value;
this.children = new ArrayList<TreeNode<T>>();
}
public final T getValue() {
return this.value;
}
public final void setValue(T value) {
this.value = value;
}
public final int getChildrenCount() {
return this.children.size();
}
public final void addChild(TreeNode<T> child) {
if (child == null) {
throw new IllegalArgumentException("Cannot insert null value!");
}
if (child.hasParent) {
throw new IllegalArgumentException("The node already has a parent!");
}
child.hasParent = true;
this.children.add(child);
}
public final TreeNode<T> getChild(int index) {
return this.children.get(index);
}
Tree
public class Tree<T> {
TreeNode<T> root;
public Tree(T value) {
if (value == null) {
throw new IllegalArgumentException("Cannot insert null value!");
}
this.root = new TreeNode<T>(value);
}
public Tree(T value, Tree<T>... children) {
this(value);
for (Tree<T> child : children) {
this.root.addChild(child.root);
}
}
public final TreeNode<T> getRoot() {
return this.root;
}
Here i can use all inner roots and all nodes.
while (!stack.isEmpty()) {
TreeNode<Integer> currentNode = stack.pop();
for (int i = 0; i < currentNode.getChildrenCount(); i++) {
TreeNode<Integer> childNode = currentNode.getChild(i);
if (childNode == null) {
System.out.println("Not a root.");
} else {
System.out.println(childNode.getValue());
counter += childNode.getChildrenCount();
}
}
}

How to Traverse a N-Ary Tree

My Tree/Node Class:
import java.util.ArrayList;
import java.util.List;
public class Node<T> {
private T data;
private List<Node<T>> children;
private Node<T> parent;
public Node(T data) {
this.data = data;
this.children = new ArrayList<Node<T>>();
}
public Node(Node<T> node) {
this.data = (T) node.getData();
children = new ArrayList<Node<T>>();
}
public void addChild(Node<T> child) {
child.setParent(this);
children.add(child);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getParent() {
return this.parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
public List<Node<T>> getChildren() {
return this.children;
}
}
I know how to traverse a Binary Tree, but traversing a N-Ary seems much more tricky.
How would I go about traversing through this tree. I want a counter whilst I traverse the tree as to number/count each node in the tree.
Then at a specific count, I can stop and return the node at that count (perhaps remove that subtree or add a subtree at that position).
The simplest way is to implement a Visitor pattern like this:
public interface Visitor<T> {
// returns true if visiting should be cancelled at this point
boolean accept(Node<T> node);
}
public class Node<T> {
...
// returns true if visiting was cancelled
public boolean visit(Visitor<T> visitor) {
if(visitor.accept(this))
return true;
for(Node<T> child : children) {
if(child.visit(visitor))
return true;
}
return false;
}
}
Now you can use it like this:
treeRoot.visit(new Visitor<Type>() {
public boolean accept(Node<Type> node) {
System.out.println("Visiting node "+node);
return false;
}
});
Or for your particular task:
class CountVisitor<T> implements Visitor<T> {
int limit;
Node<T> node;
public CountVisitor(int limit) {
this.limit = limit;
}
public boolean accept(Node<T> node) {
if(--limit == 0) {
this.node = node;
return true;
}
return false;
}
public Node<T> getNode() {
return node;
}
}
CountVisitor<T> visitor = new CountVisitor<>(10);
if(treeRoot.visit(visitor)) {
System.out.println("Node#10 is "+visitor.getNode());
} else {
System.out.println("Tree has less than 10 nodes");
}

Recursive Graph Traversal

I'm writing a program in Java to solve puzzles from this game:
http://universefactory.net/0/
I've modeled the problem as follows
Node Class:
package model;
import java.util.ArrayList;
public class Node {
private final int nodeId;
private ArrayList<Edge> edges;
ArrayList<Edge> getEdges() {
return edges;
}
public int getNodeId() {
return nodeId;
}
public Node(int id) {
nodeId = id;
edges = new ArrayList<Edge>();
}
#SuppressWarnings("unused")
private Node() {
nodeId = -1;
}
private void addEdge(Edge toBeAdded) {
if (toBeAdded != null)
edges.add(toBeAdded);
}
public void addEdgeTo(Node to, Star star) {
if(this.equals(to))
return;
if (to != null) {
Edge edge = new Edge(to, star);
addEdge(edge);
}
}
public void addEdgeTo(Node to) {
if(this.equals(to))
return;
if (to != null) {
Edge edge = new Edge(to);
addEdge(edge);
}
}
public Edge getEdge(Node to)
{
Node edgeDestination;
for(Edge edgeIterator: edges)
{
edgeDestination = edgeIterator.goesTo();
if(edgeDestination.equals(to))
return edgeIterator;
}
return null;
}
public Edge popEdge(Node to)
{
Node edgeDestination;
for(Edge edgeIterator: edges)
{
edgeDestination = edgeIterator.goesTo();
if(edgeDestination.equals(to))
{
edges.remove(edgeIterator);
return edgeIterator;
}
}
return null;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (nodeId != other.nodeId)
return false;
return true;
}
}
Edge class:
package model;
public class Edge {
private final Star star;
private final Node to;
Edge(Node nodeTo) {
star = null;
to = nodeTo;
}
Edge(Node nodeTo, Star star) {
this.star = star;
to = nodeTo;
}
public void consumeEdge() {
if (star != null) {
star.die();
}
}
public boolean consumable() {
if (star == null)
return false;
return star.isAlive();
}
public Node goesTo() {
return to;
}
}
Star Class
package model;
public class Star {
boolean dead = false;
public void die() {
dead = true;
}
public boolean isAlive()
{
return !dead;
}
}
and Graph Class:
package model;
import java.util.ArrayList;
public class Graph {
private ArrayList<Node> nodes = null;
private ArrayList<Star> stars = null;
private Node startNode = null;
private final int startNodeID = 0;
public Graph(ArrayList<Node> nodeArr, ArrayList<Star> starArr) {
// TODO Auto-generated constructor stub
nodes = nodeArr;
stars = starArr;
setStartNode();
}
private void setStartNode() {
for (Node nodeIterator : nodes) {
if (nodeIterator.getNodeId() == startNodeID) {
startNode = nodeIterator;
break;
}
}
}
public Graph(Graph other) {
nodes = new ArrayList<Node>();
stars = new ArrayList<Star>();
nodes.addAll(other.getNodes());
stars.addAll(other.getStars());
setStartNode();
}
public ArrayList<Node> solve() {
final int numberOfStars = stars.size();
ArrayList<Node> solution = new ArrayList<Node>();
solution.add(startNode);
recursiveSolver(startNode, numberOfStars, solution);
return solution;
}
private boolean recursiveSolver(Node currentNode, int numberOfStars,
ArrayList<Node> solutionPointer) {
if (numberOfStars == 0)
return true;
for(Edge edgeIterator: currentNode.getEdges())
{
Node nextNode = edgeIterator.goesTo();
Graph deepCopy = new Graph(this);
currentNode = deepCopy.getNode(currentNode);
nextNode = deepCopy.getNode(nextNode);
//deepCopy.traverse(currentNode, nextNode);
//deepCopy.recursiveSolver(.....);
//Not sure how to finish this <---------------------------PROBLEM AREA
}
}
private Node getNode(Node currentNode) {
return getNode(currentNode.getNodeId());
}
private ArrayList<Node> getNodes() {
return nodes;
}
private ArrayList<Star> getStars() {
return stars;
}
public void linkNodesWith(int fromNodeID, int toNodeID, Star star) {
final Node from = getNode(fromNodeID);
final Node to = getNode(toNodeID);
if (from != null && to != null)
linkNodesWith(from, to, star);
}
private void linkNodesWith(Node nodeFrom, Node nodeTo, Star star) {
nodeFrom.addEdgeTo(nodeTo, star);
nodeTo.addEdgeTo(nodeFrom, star);
}
public Node getNode(int nodeId) {
for (Node iteratorNode : nodes) {
if (iteratorNode.getNodeId() == nodeId)
return iteratorNode;
}
return null;
}
public void removeNode(Node nodeToRemove) {
nodes.remove(nodeToRemove);
for (Node nodeIterator : nodes) {
nodeIterator.popEdge(nodeToRemove);
}
}
public void removeNode(int nodeIdToRemove) {
Node nodeToRemove = getNode(nodeIdToRemove);
removeNode(nodeToRemove);
}
//Last three functions are used to create a specific graph to solve
public void populateEdges() {
for (Node nodeFromIterator : nodes) {
for (Node nodeToIterator : nodes) {
nodeFromIterator.addEdgeTo(nodeToIterator);
}
}
}
public void replaceEdge(int nodeFromID, int nodeToID, Star star) {
Node nodeFrom = getNode(nodeFromID);
Node nodeTo = getNode(nodeToID);
unlinkNodes(nodeFrom, nodeTo);
linkNodesWith(nodeFrom, nodeTo, star);
}
private void unlinkNodes(Node nodeFrom, Node nodeTo) {
nodeFrom.popEdge(nodeTo);
nodeTo.popEdge(nodeFrom);
}
}
I can't figure out a way to solve this without making deep copies of the graph every time a node is deleted/traversed, and even then am not sure as to how I can save the path in an array-list. Is there a better way to model the problem that would simplify the solution?
universefactory.net/0 : the game im trying to write a solution for.
You can do this with a recursive backtracking solution and an immutable graph, for example
1) Construct a graph of all nodes + all edges and a list of stars (each star containing a list of all edges it is on, OR each edge containing a list of references to stars (not copies) that are on its path. Whatever makes more sense to you)
2) Write a recursive method. Its parameters will be:
the graph + list of stars (immutable)
the list of nodes taken so far, in order
the list of edges taken so far, in order
the list of stars left to take
It should do the following:
2a) If it has possible moves to take (edges from the node it's on that aren't in the list of edges taken so far), recursively branch and try each of those next moves, by calling itself with
the graph + list of stars (immutable)
a copy of the list of edges taken so far, in order, adding the new edge taken by this mode
a copy of the list of nodes taken so far, in order, adding the new node taken by this mode
a copy of the list of stars left to take, subtracting new stars taken by this move
2b) If it has no possible modes to take, check if we have taken all stars. If we have, then this is the solution (print out the list of edges taken)

Categories

Resources