Find the path from leaf to root in Tree - java

I saw a lot of examples about Trees and how to recursively search them, but not like my case. So I decide to ask.
How can I find a path from any leaf to the root?
My problem is that I have a lot of child nodes per parent. Here is an example of my code:
private LinkedList<TreeNode> findPath(LinkedList<TreeNode> path, TreeNode root, TreeNode leaf){
if(root == null || root.name==null) return null;
path.add(root);
if(root.name.equals(leaf.name))
return path;
//Check if the leaf that we are looking for is one of the root children
if(root.children==null) return null;
for(TreeNode children : root.children){
if(children.name.equals(leaf.name)){
path.add(children);
return path;
}
}
//Search in all the childrens of the root recursively
for(TreeNode children : root.children){
LinkedList<TreeNode> result = findPath(path, children, leaf);
if(result != null)
return result;
}
//The leaf is not found.
return null;
}
And the problem is that every time when I check a child, if I don't find my leaf there I take back but I have add the child node in the path and my path becomes very big.

This implementation assumes that every tree node 'knows' its parent:
private List<TreeNode> findPath(TreeNode root, TreeNode leaf) {
List<TreeNode> path = new ArrayList<>();
TreeNode node = leaf;
do {
path.add(node);
node = node.getParent();
} while (node != root);
return path;
}
Of course you should add validity check for root and leaf and think of the possibility of an infinite loop if a node is (directly or indirectly) its own parent.
If your tree nodes only contain their children, but a child node does not 'know' its parent (which you probably should change if you own the code of the tree nodes), its getting more complex, as the tree must be searched recursively:
public static List<TreeNode> findPath(TreeNode root, TreeNode leaf) {
LinkedList<TreeNode> path = new LinkedList<>();
findPathHelper(root, leaf, path);
return path;
}
private static boolean findPathHelper(TreeNode root, TreeNode leaf, List<TreeNode> path) {
if (root == leaf) {
path.add(root);
return true;
}
for (TreeNode treeNode : root.children) {
if (findPathHelper(treeNode, leaf, path)) {
path.add(root);
return true;
}
}
return false;
}

Related

Java implement tree search

I'd like to implement and test a tree search function. I'm using the DefaultTreeModel of javax.swing. I operato on my own defined Employee objects as the tree data. I tried to get the following to work:
private DefaultMutableTreeNode search(int id, DefaultMutableTreeNode node){
if(node != null){
Employee emp = (Employee) node.getUserObject();
if(emp.getId() == id){
return node;
} else {
DefaultMutableTreeNode foundNode = search(id, node.getPreviousSibling());
if(foundNode == null) {
foundNode = search(id, node.getNextSibling());
}
return foundNode;
}
} else {
return null;
}
}
but it can only find the element which is among one parent's siblings. And like to find it in entire tree, from root to leaves. How do I do it?
You could navigate to the root of the tree first in a different method, then call your current recursive method.
private DefaultMutableTreeNode search(int id, DefaultMutableTreeNode node){
if(node == null){
return null;
}
node = node.getRoot(); //Turns out that this class has a getRoot() method.
return searchInternal(id,node); //Then does a depth-first search from the root node.
}
private DefaultMutableTreeNode searchInternal(int id, DefaultMutableTreeNode node){
if(node == null){ //I also switched this around, for good practice.
return null;
}
Employee emp = (Employee) node.getUserObject();
if(emp.getId() == id){ //Found it!
return node;
}
DefaultMutableTreeNode foundNode = searchInternal(id, node.getPreviousSibling());
if(foundNode == null) {
foundNode = search(id, node.getNextSibling());
}
return foundNode;
}
In general, recursive methods tend to run a bit slower in Java, and they are prone to stack overflowing. It's usually better to use a custom stack for depth-first search, and this doesn't require you to make a different method. Recursive methods might make the code more readable in some cases.
What also works, in this case:
private DefaultMutableTreeNode search(int id, DefaultMutableTreeNode node){
if(node == null){
return null;
}
Enumeration enumeration = node.getRoot().depthFirstEnumeration(); //Enumerate over all nodes in the tree.
while(enumeration.hasMoreElements()){
DefaultMutableTreeNode next = enumeration.next();
if(((Employee)next.getUserObject()).getId() == id){ //Found it!
return next;
}
}
return null;
}
Turns out that depth-first searching is already implemented by Swing. This is a post-order enumeration though. See the javadoc, there are also methods for the other types of traversals.

finding parent in binary search tree

Here is the code to find parent in Binary search tree. I am not able to understand how is it working, as we are never assigning any value to parent other than null. I an new to recursion.
public Node findParent(Type data)
{
return findParent(data, root, null);
}
public Node findParent(Type x, Node node, Node parent)
{
if (node == null) {
return null;
} else if (!(node.data == x)) {
parent = findParent(x, node.left, node);
if (parent == null) {
parent = findParent(x, node.right, node);
}
}
return parent;
}
You are assigning a non null value to parent in the recursive calls :
parent = findParent(x, node.left, node);
----
parent = findParent(x, node.right, node);
----
parent is null only in the initial call (since the root of the tree has no parent).
Each call to findParent gets a value (x), a Node (node) and the parent Node of that Node (parent). If that value is found in the Node, parent is returned, otherwise, you search for that value in the left sub-tree, and if it's still not found, you search for it in the right sub-tree.
Here I put some comments in it. Tell me if it not seems clear. (Recursion is hard to explain)
// The method
public Node findParent(Type x, Node node, Node parent)
{
// if this node is null, return null, cause this
// is not the path you are looking for
if (node == null) {
return null;
// if this is not the node we are looking for,
} else if (!(node.data == x)) {
// We look in the left node.
parent = findParent(x, node.left, node);
// If its not found parent will be null
if (parent == null) {
// So we go look to the right
parent = findParent(x, node.right, node);
}
}
// Eventually we can return the parent.
// If this was the node we were looking for,
// We can return parent without changing it.
// If it was not, this algorithm searched in its subtrees
// If its not there than parent is null.
return parent;
}

How to find the next in order successor in a binary tree?

I'm trying to implement an Iterator in my own TreeSet class.
However my attempt at creating it only works until the current node is the root.
The Iterator looks like this:
Constructor:
public TreeWordSetIterator()
{
next = root;
if(next == null)
return;
while(next.left != null)
next = next.left;
}
hasNext:
public boolean hasNext()
{
return next != null;
}
Next:
public TreeNode next()
{
if(!hasNext()) throw new NoSuchElementException();
TreeNode current = next;
next = findNext(next); // find next node
return current;
}
findNext:
private TreeNode findNext(TreeNode node)
{
if(node.right != null)
{
node = node.right;
while(node.left != null)
node = node.left;
return node;
}
else
{
if(node.parent == null)
return null;
while(node.parent != null && node.parent.left != node)
node = node.parent;
return node;
}
}
This works fine up until I get to my root node. So I can only iterate through the left child of root, not the right. Can anyone give me a few tips on what I'm doing wrong? I don't expect a solution, just a few tips.
Question: How can I find the next node in a TreeSet given each node points to its parent, left-child and right-child.
Thanks in advance
It helps to consider the rules of a Binary Search Tree. Let's suppose the previously returned node is n:
If n has a right subtree, then the node with the next value will be the leftmost node of the right subtree.
If n does not have a right subtree, then the node with the next value will be the first ancestor of n that contains n in its left subtree.
Your code is correctly handling the first case, but not the second. Consider the case where node is the leftmost leaf of the tree (the starting case). node has no right child, so we go straight to the else. node has a parent, so the if-clause is skipped. node.parent.left == node, so the while clause is skipped without executing at all. The end result is that node gets returned. I'd expect your iterator to continue returning the same node forever.
There are 3 main ways you can iterate a binarry tree
private void inOrder(TreeNode node) {
if(isEmpty())return;
if(node.getLeftNode()!=null)inOrder(node.getLeftNode());
System.out.print(node.getNodeData()+" ");
if(node.getRightNode()!=null)inOrder(node.getRightNode());
}
private void preOrder(TreeNode node) {
if(isEmpty())return;
System.out.print(node.getNodeData()+" ");
if(node.getLeftNode()!=null)preOrder(node.getLeftNode());
if(node.getRightNode()!=null)preOrder(node.getRightNode());
}
private void postOrder(TreeNode node) {
if(isEmpty())return;
if(node.getLeftNode()!=null)postOrder(node.getLeftNode());
if(node.getRightNode()!=null)postOrder(node.getRightNode());
System.out.print(node.getNodeData()+" ");
}
//use
inOrder(root);
preOrder(root);
postOrder(root);
Its simple as that ,your code doesn't really makes sense to me, is there something else you are trying to do besides iterating in one of this ways?
I think you need to save previous point in your iterator so you know where you've been before
Here some code but be aware that it is not complete you should do it by yourself and it's just to show you the idea. it also doesn't handle the root node.
findNext(TreeNode node, TreeNode previousNode) {
if(node.left != null && node.left != previousNode && node.right != previousNode){ //go left if not been there yet
return node.left;
}
if(node.right != null && node.right != previousNode){ //go right if not been there yet
return node.right;
}
return findNext(node.parent, node); //go up and pass current node to avoid going down
}
A good approach is to use a stack to manage sequencing, which is sort of done for you if you use a recursive traversal (instead of trying to build an Iterator at all) as described in SteveL's answer.
As you want to start from the left, you first load onto the stack the root node and its leftmost children in the proper order (push while going down to the left from the root).
Always pop the next from the top of the stack, and push its right child (if any) and all its leftmost children before returning the one you just popped, so that they're next in line.
By this approach, the top of the stack will always be the next to return, and when the stack is empty, there's no more...
In code:
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;
public class TreeNodeInOrderIterator<T> implements Iterator<T> {
private final Stack<TreeNode<T>> stack;
public TreeNodeInOrderIterator(TreeNode<T> root) {
this.stack = new Stack<TreeNode<T>>();
pushLeftChildren(root);
}
#Override
public boolean hasNext() {
return !stack.isEmpty();
}
#Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
TreeNode<T> top = stack.pop();
pushLeftChildren(top.right);
return top.val;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
private void pushLeftChildren(TreeNode<T> cur) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
}
}
In this code, TreeNode is defined by
public class TreeNode<T> {
T val;
TreeNode<T> left;
TreeNode<T> right;
TreeNode(T x) { val = x; }
}
If you want to have each node also know its parent, that's ok, but all the traversal is by using what's on the stack and adding to the stack using the left and right child links.

Find path to node in Tree?

I have a tree class that looks like:
Class Tree {
Node root;
Node curNode;
public List<String> find(String value) {
if (curNode == null) curNode = root;
for (Node child : curNode.children) {
if (found == false) {
if (child.data.equals(value)) {
// if it finds it return the path to this node.
}
curNode = child;
findDFS(value);
}
}
}
class Node {
List<Node> children;
String data;
}
Where the tree root contains pointers to children nodes which point to other children etc etc. What I'm having problems with is once it finds the node, I need to return the the path to that node.
passing a list tracking the path, once find the node, exit the recursion and fill the path one by one.
Boolean Search(Node node, String value, List<Node> track)
{
if (node == null) return false;
if (node.data.equals(value))
{
track.add(node);
return true;
}
for(Node child : node.children)
{
if (Search(child, value, track)
{
track.add(0, node);
return true;
}
}
return false;
}
If the nodes only point to their children, you'll need to keep track of each path on the way down. As mentioned in comment, you can do this with your own stack or with recursion. For example, you could always return find() call on the children of each node.
If the nodes point both ways, you can easily re-trace the path up once you find the correct node.
The following code traces the path, adding nodes to the list and removing them if they are not in the path
boolean getPath(Node root,String targetValue,List<Integer> path)
{
// base case root is null so path not available
if(root==null)
return false;
//add the data to the path
path.add(root.getData());
//if the root has data return true,path already saved
if(root.getData().equals(targetValue))
return true;
//find the value in all the children
for(Node child: children){
if(getPath(child,targetValue,path))
return true;
}
//if this node does not exist in path remove it
path.remove(path.size()-1);
return false;
}

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;
}

Categories

Resources