Depth first search in java - how to go back to parent node? - java

I'm trying to do a depth first search in Java recursively. At the moment, the code runs through my graph fine, but it never backtracks to find a route when they're are no more nodes to visit. I'm having a bit of a mental block honestly. What would be the best way to go back to the parent node?
Here is my code so far:
private final Map<Character, Node> mNodes;
private final List<Edge> mEdges;
public DepthFirstSearch(Graph graph){
mNodes = graph.getNodes();
mEdges = new ArrayList<>(graph.getEdges());
for(Node node : mNodes.values()){
node.setVisited(false);
}
}
public void depthFirstSearch(Node source){
source.setVisited(true);
List<Node> neighbours = source.getNeighbours(mEdges);
for(Node node : neighbours){
if(!node.isVisited()){
System.out.println(node.getName());
depthFirstSearch(node);
}
}
}
And the getNeighbour code:
public List<Node> getNeighbours(List<Edge> edges) {
List<Node> neighbours = new ArrayList<>();
for(Edge edge : edges){
if(edge.getFrom().equals(this)){
neighbours.add(edge.getTo());
}
}
return neighbours;
}
Added code for trying Jager's idea:
public void depthFirstSearch(Node source){
source.setVisited(true);
List<Edge> neighbours = source.getNeighbouringEdges(mEdges);
for(Edge edge : neighbours){
if(!edge.getTo().isVisited()){
System.out.println(edge.getTo().getName());
depthFirstSearch(edge.getTo());
}else{
depthFirstSearch(edge.getFrom());
}
}
}

Well, typically you have a root node that has children. Each child can have children of its own. So you would rather do:
public void depthFirstSearch(Node source)
{
for(Node node : source.getChildren())
{
System.out.println(node.getName());
depthFirstSearch(node);
// and right here you get your back tracking implicitly:
System.out.println("back at " + node.getName());
}
}
Note that I do not have a necessity for a member visited...
Edit:
Now that you provided your data structure, let me propose another approach:
class Node
{
// all that you have so far...
private char mId;
private List<Node> mChildren = new ArrayList<Node>();
public char getId()
{
return mId;
}
public List<Node> getChildren()
{
return Collections.unmodifiableList(children);
}
// appropriate methods to add new children
}
The id replaces the key of your map. Then you simply have a root Node mRoot to start with somewhere. This is the typical way to implement trees.
You might want to go up from a child node directly. Then you'd additionally need a private Node parent; in the node class (immediately being set to this when adding a child to the private list and set to null, when being removed). You won't use this for backtracking, though, so the depth first search above remains unchanged.

Guessing: you are "getting" the neighbors for mEdges which seems to be a field of the surrounding class.
Most likely, you should ask each node for its own edges upon visiting it.

Related

Recursion of Level Order Traversal of N-ary tree

I am currently working on N-ary trees and I stumbled upon Level Order Traversal. It seemed very easy on theory , not so difficult to run on code , but now I want to step it up and add recursion so I can wrap my head around it better. The things is I am now finding it very difficult to do so. There is my code for:
- The node class
import java.util.ArrayList;
import java.util.List;
/**
* Implementation of a generic tree node containing the data and a list of children.
*
* #param <T> Generic type meant to implement reference types into the tree.
*/
public class Node<T> {
private T data;
private List<Node<T>> children;
/**
* Constructor that initializes the data and the list of children of the current node.
*
* #param data The value of the node.
*/
public Node(T data) {
this.data = data;
children = new ArrayList<>();
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public List<Node<T>> getChildren() {
return children;
}
public void setChildren(List<Node<T>> children) {
this.children = children;
}
}
-The tree class
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/** Implementation of a generic n-ary tree. */
public class Tree<T> {
private Node root;
private List<Node<T>> nodes;
/**
* Constructor that initializes the root node of the tree.
*
* #param data The value of the root node.
*/
public Tree(T data) {
root = new Node<>(data);
}
public Node getRoot() {
return root;
}
/**
* Method that implements the Level Order Traversal algorithm. It's a left to right traverse where
* each level of the tree is being printed out. First the root , then it's children and then each
* child's children etc.
*
* #param root The root node of a tree.
*/
public String levelOrderTraversal(Node root) {
StringBuilder result = new StringBuilder();
if (root == null) {
return "";
}
result.append("\n");
Queue<Node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
int queueSize = q.size();
while (queueSize > 0) {
Node node = q.peek();
q.remove();
result.append(node.getData().toString()).append(" ");
for (int i = 0; i < node.getChildren().size(); i++) {
q.add((Node) node.getChildren().get(i));
}
queueSize--;
}
result.append("\n");
}
return result.toString();
}
/**
* This method serves to recursively move through and retrieve the nodes, so they can be printed
* out to the user.
*
* #param root The root node of the tree.
*/
private void walkThroughElements(Node root) {
if (root == null) {
return;
}
nodes.add(root);
for (Object node : root.getChildren()) {
walkThroughElements((Node) node);
}
}
/**
* Implementation of pre-order traversal of a generic tree. This traversal visit the root node
* first , prints it , then visits the whole left sub-tree (the list of every child node), prints
* every node and then traverses the right sub-tree , prints the nodes and ends the algorithm.
*
* #param root The root node of the tree.
* #return The nodes of the tree as a string.
*/
private String preOrderTraversal(Node<T> root) {
nodes = new ArrayList<>();
StringBuilder result = new StringBuilder();
walkThroughElements(root);
for (Node node : nodes) {
result.append(node.getData()).append(" ");
}
result.setLength(result.length() - 1);
return result.toString();
}
public String preOrderTraversal() {
return preOrderTraversal(root);
}
}
Is there an efficient way or does it even make sense to run this level order traversal method recursively?
This is the level order code after some changes
public String levelOrderTraversal(Node root) {
StringBuilder result = new StringBuilder();
if (root == null) {
return "";
}
result.append("\n");
Queue<Node> q = new LinkedList<>();
q.add(root);
collectNodes(root, root.getChildren());
result.append(root.getData().toString()).append(" ");
result.append("\n");
return result.toString();
}
It gives the error on the line where collectNodes is called.
This is what collectNodes() looks like.
private void collectNodes(Node<T> node, List<Node<T>> nodes) {
nodes.add(node);
for (Object child : node.getChildren()) {
collectNodes((Node) child, nodes);
}
}
You can solve those iteration problems using iteration (e.g. via a stack) or recursion. Let's use a method that gathers nodes much like your walkThroughElements():
Depth-first
Recursion
//add the node and then go deeper
void collect(Node node, Collection<Node> nodes) {
nodes.add(node);
for(Node child : node.getChildren()) {
collect(child, nodes);
}
}
Iteration
class Level {
final Node node;
Iterator<Node> childItr;
//constructor, setters, getters
}
void collect(Collection<Node> nodes) {
Stack<Level> levels = new Stack<>();
nodes.add(root);
levels.push(new Level(root, root.getChildren().iterator()));
while( !levels.isEmpty() ) {
Level currentLevel = levels.peek();
//remove the current level as it doesn't have any more children
if( !currentLevel.childItr.hasNext() ) {
levels.pop();
} else {
//get the next child and add it to the result
Node child = currentLevel.childItr.next();
nodes.add(child);
//go down to the child's level
levels.push(new Level(child, child.getChildren().iterator())
}
}
}
Breadth-first
Recursion
//add the children first (i.e. the entire level) and then go deeper
void collectChildren(Node node, Collection<Node> nodes) {
for(Node child : node.getChildren()) {
nodes.add(child);
collectChildren(child, nodes);
}
}
//special case: root node
void collect(Collection<Node> nodes) {
nodes.add(root);
collectChildren(root, nodes);
}
Iteration
void collect(Collection<Node> nodes) {
Queue<Node> nodesToProcess = new LinkedList<>();
nodesToProcess.add(root);
while( !nodesToProcess.isEmpty() ) {
Node node = nodesToProcess.poll();
nodes.add(node);
nodesToProcess.addAll(node.getChildren());
}
}
As you can see, recursion is easier on depth-first than breadth-first but easy to read anyway. Recursion will use the call stack to maintain state so it takes up (non-heap) memory and also has limits to its depth (depends on how much memory there is but the infamous StackOverflowException would tell you there's either a bug or the tree is too deep).
Iteration is easier with breadth first and requires additional constructs like a stack or a queue. It requires some heap memory for those constructs and may be faster due to some optimizations but in general I'd not bother about performance differences here as they should only manifest themselves for really large trees - and in that case recursion might hit the call stack limit already.
Using recursion typically will be slower than iteration and use more stack space as well.But Yes,this can also be solved using recursive way(DFS approach).
For your reference : https://leetcode.com/problems/binary-tree-level-order-traversal/discuss/33562/Java-1ms-DFS-recursive-solution-and-2ms-BFS-iterative-solution
The proper way is to do it in a lazy way
// assume not null Node::data (if so, wrap into Optional or similar)
static <T> Stream<T> levelOrderTraversal(Node<T> tree) {
final List<Node<T>> fifo = new ArrayList<>();
if(tree != null)
fifo.add(tree);
final Function<T, T> next = o -> {
if(fifo.isEmpty())
return null; // End Of Stream
Node<T> x = fifo.remove(0);
System.out.println("++++++ " + x.data);
if(x.children != null)
fifo.addAll(x.children);
return x.data;
};
return Stream.iterate(null, next::apply).skip(1).takeWhile(Objects::nonNull);
}
for example
++++++ foo
foo
++++++ bar1
bar1
++++++ bar2
bar2
++++++ par11
par11
++++++ par12
par12
++++++ par21
par21
++++++ par22
par22
++++++ subA
subA
++++++ subB
subB
where you only mantain the intermediate traversing level (not the whole tree).
For example, if you log every node expansion and filter the tree, not all nodes are logged
levelOrderTraversal(tree)
.takeWhile(x -> !x.equals("bar2"))
.forEach(System.out::println);
only expand the foo, bar1 and bar2 nodes
++++++ foo
foo
++++++ bar1
bar1
++++++ bar2

How to detect loop before adding child Node to parent Node Java

I have a Node model like below with list of child nodes:
class Node {
private String name;
private List<Node> childNodes;
public Node(String name, List<Node> childNodes) {
this.name = name;
this.childNodes = childNodes;
}
public Node(String name) {
this(name, new ArrayList<>());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Node> getChildNodes() {
return childNodes;
}
public void setChildNodes(List<Node> childNodes) {
this.childNodes = childNodes;
}
public void addChildNodes(Node childNode) {
this.getChildNodes().add(childNode);
}
}
What I am going to do is checking if a loop is produced when adding a child node to a parent node. Loop here means a child node has the same name as its direct or indirect parent. And when the loop is detected, I would like to print out also which nodes are content in this loop. What I have done sofar is:
private static void findLoop(Node currentNode, String orginalNodeName, String visitedNode) {
if (currentNode != null && !currentNode.getChildNodes().isEmpty()) {
for (Node childNode : currentNode.getChildNodes()) {
visitedNode = visitedNode + "->" + childNode.getName();
if (childNode.getName().equals(orginalNodeName)) {
System.out.println("Loop is detected: " + visitedNode);
}
findLoop(childNode, orginalNodeName, visitedNode);
}
}
}
My idea is looping through all the child nodes, start from the node that I want to check, and compare if the current node has the same name as the original starting Node, if yes then a loop is detected.
It works but I can not print the content of the loop correctly, because it loop through all of the possible child nodes of a parent node, ex:
parentNode
node1 node2
childNode1 childNode2
parentNode childChildNode2
It printed: parentNode->node1->node2->childNode2->parentNode and what I would like to print is : parentNode->node2->childNode2->parentNode
Can anyone give me some hint here? Thank you so much!
Since you are pretty close to the result that you would like to get, here are several hints for you on how to complete the task:
findLoop needs to return boolean - otherwise you would not know when to stop iterating at the higer levels of recursion
visitedNode needs to be a List<Node> - otherwise you are stuck with a single item's name
When findLoop inside for(...) returns true, method returns true immediately - this makes sure that a positive does not get ignored
Finally, don't forget that findLoop needs to start with the child node, and loop for the parent node, not the other way around.

How to deep copy a Binary Tree?

I would like using my own Node class to implement tree structure in Java. But I'm confused how to do a deep copy to copy a tree.
My Node class would be like this:
public class Node{
private String value;
private Node leftChild;
private Node rightChild;
....
I'm new to recursion, so is there any code I can study? Thank you!
try
class Node {
private String value;
private Node left;
private Node right;
public Node(String value, Node left, Node right) {
this.value = value;
...
}
Node copy() {
Node left = null;
Node right = null;
if (this.left != null) {
left = this.left.copy();
}
if (this.right != null) {
right = this.right.copy();
}
return new Node(value, left, right);
}
}
Doing it recursively using pre-order traversal.
public static Node CopyTheTree(Node root)
{
if (root == null)
{
return null;
}
Node newNode = new Node(null, null, root.Value);
newNode.Left= CopyTheTree(root.Left);
newNode.Right= CopyTheTree(root.Right);
return newNode;
}
You can use something like this. It will go though the old tree depth first wise and create a copy of it.
private Tree getCopyOfTree(oldTree) {
Tree newTree = new Tree();
newTree.setRootNode(new Node());
copy(oldTree.getRootNode(), newTree.getRootNode())
return newTree;
}
private void copy(Node oldNode, Node newNode) {
if (oldNode.getLeftChild != null) {
newNode.setLeftChild(new Node(oldNode.getLeftChild()));
copy(oldNode.getLeftChild, newNode.getLeftChild());
}
if (oldNode.getRightChild != null) {
newNode.setRightChild(new Node(oldNode.getRightChild()));
copy(oldNode.getRightChild, newNode.getRightChild());
}
}
I like Evgeniy Dorofeev's answer above, but sometimes you might not be able to add a method to the type Node as you might not own it. In that case(this is in c#):
public static TreeNode CopyTree(TreeNode originalTreeNode)
{
if (originalTreeNode == null)
{
return null;
}
// copy current node's data
var copiedNode = new TreeNode(originalTreeNode.Data);
// copy current node's children
foreach (var childNode in originalTreeNode.Children)
{
copiedNode.Children.Add(CopyTree(childNode));
}
return copiedNode;
}
Not sure but try something with post order traversal of your tree and creating a new node for each node you traverse. You might require stack for storing the nodes you created to make left and right child links.
public static TreeNode copy( TreeNode source )
{
if( source == null )
return null;
else
return new TreeNode( source.getInfo( ), copy( source.getLeft( ) ), copy( source.getRight( ) ) );
}
/Sure. Sorry for the delay. Anyway... any recursive method has a base case, and one or more recursive cases. In this instance, the first line is obvious... if the argument to the parameter 'source' is null (as it eventually evaluates to in order to end the method's operation), it will return null; if not, the recursive case is initiated. In this case, you're returning the entire copied tree once the recursion is complete.
The 'new' operator is used, indicating the instantiation of a TreeNode with each visit to the various nodes of the tree during the traversal, occurring through recursive calls to 'copy', whose arguments become references to the left and right TreeNodes (if there are any). Once source becomes null in each argument, the base case is initiated, releasing the recursion stack back to the original call to 'copy', which is a copy of the root of the original tree./
Node copy(Node node)
{
if(node==null) return node;
Node node1 =new Node(node.data);
node1.left=copy(node.left);
node1.right=copy(node.right);
return node1;
}

Iterators over Tries in Java

I am currently trying to implement a trie data structure for integer tuples. And have implemented as follows:
import java.util.ArrayList;
public class TrieNode {
int num;
ArrayList<TrieNode> links;
boolean endOfTuple;
public TrieNode(int num)
{
this.num = num;
links = new ArrayList<TrieNode>();
this.endOfTuple = false;
}
}
I then have a trie class as follows:
public class Trie {
TrieNode root;
public Trie() {
root = new TrieNode(-1);
}
public void insertTuple(int[] tuple)
{
int l = tuple.length;
TrieNode curNode = root;
for (int i = 0; i < l; i++)
{
TrieNode node = new TrieNode(tuple[i]);
if(!curNode.links.contains(node)){
curNode.links.add(node);
}
curNode = curNode.links.get(curNode.links.indexOf(node));
}
curNode.endOfTuple = true;
}
}
I can add values to this trie, but i need to be able to iterate over this and was wondering how i could do this? For example if i wanted to print the tree using an iterator...Any help will be great...
All you need for an interator is to implement the Iterator interface, which only requires that you supply boolean hasNext() and Integer next(). So the question to ask is: how do represent a position in your trie, such that it's possible to (a) fetch the value associated with that position, and (b) figure out the "next" position given a current one?
I'll refrain from posting an actual solution since I'm not sure whether this is homework. But consider: you can represent a "current position" in your trie just by choosing a particular trie node, and the path of trie nodes you used to reach it. Then you can compute the "next" element recursively: if the current element is a node that has children, then find the first child for which endOfTuple is true. If the current element doesn't have children, then go to its parent and advance to that parent's next child. If that parent doesn't have next children, then go it its parent's next child, etc.

How do I loop through an array in Java?

Related to my question about how to build a tree-like structure, the data I receive from the server are in arrays like this: {School Chair Table Chalk}
How can I loop through this so that:
School becomes parent of Chair
Chair becomes parent of Table
Table becomes parent of Chalk
Assuming a Node class that offers a constructor which accepts the node's value as an argument and method addChild that adds another Node as a child and sets itself as the child's parent, the code could look like this:
Node currentNode = null;
for(String value: array) {
Node node = new Node(value);
if(currentNode != null) {
currentNode.addChild(node);
}
currentNode = node;
}
Are they always in a list that becomes hierarchical in order? I would suggest creating a simple wrapper class...pardon my syntax, as I've been playing in C# for a while now:
public class Node {
public string description;
public Node child;
public Node(List<string> descriptions) {
this.description = descriptions.RemoveAt(0);
if (descriptions.Count > 0) {
this.child = new Node(descriptions); //create child node with remaining items
}
}
}
This will take issue if you pass in a list w/ zero items to the constructor, but that's easily remedied.

Categories

Resources