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;
}
Related
I am really struggling in adding a node at the end of a double linked list, adding to the head was easy, now I really can't find a way to add to the end. It seems stupid but I'm losing a lot of time, so if anyone can help that would be appreciated. Here's my partial implementation in Java.
public class DoublyLinkedList implements Iterable<Node>, Iterator<Node> {
private Node head = new Node();
private Node tail = head;
private Node current;
private Node previous;
#Override
public Iterator<Node> iterator() {
current = head;
previous = null;
return this;
}
public void addToHead(Node node) {
Node next = head.getNext(null);
Node previous = head.getNext(next);
head.setNext(previous, node);
node.setNext(null, head);
head = node;
}
#Override
public boolean hasNext() {
return current != tail;
}
#Override
public Node next() {
Node tmp = previous;
previous = current;
current = current.getNext(tmp);
return previous;
}
And here's Node Class
public class Node {
Node next = null;
Node previous = null;
Node getNext(Node node){
if(node == next){
return previous;
}
if(node == previous){
return next;
}
throw new IllegalStateException("something went wrong");
}
void setNext(Node node, Node next){
if(node == previous){
previous = next;
}
else if(node == this.next){
this.next = next;
}
else{
throw new IllegalStateException("something went wrong");
}
}
}
I hope you will understand the code above, basically I will need the following :
public void addToEnd(Node node) {
// implementation
}
What interface are you aiming to implement on this double-linked list? The way you've implemented getNext and setNext is not a clear way of doing it. If you only have one node, and you attempt to setNext with a null value for node, there is no way of telling unless you look at the code where your new node is going to end up. Along with that, I'm not sure if there is a nice way for you to set the previous node of a new tail node with the way you've implemented it. It's very ambiguous.
Can I recommend that you instead implement getNext(), setNext(Node), getPrevious() and setPrevious(Node) methods in your Node class? This would greatly simplify and clear up your code.
You would then be able to implement your addToEnd(Node) method very simply.
public void addToEnd(Node node) {
node.setPrevious(tail);
tail.setNext(node);
tail = node;
}
If you want to be able to iterate through the list in both directions using 'getNext()' and 'hasNext()', you could provide a forward or reverse Iterator implementation. There are examples of how to create Iterators floating around. The first answer on this question has an example of a reverse iterator.
The basic idea is just the same as adding at the beginning of the list.
We can split it up into two parts:
adding the item to the list
updating the head/tail-node of the list
In pseudocode:
node to_insert
//step 1
tail.setNext(to_insert)
to_insert.setPrevious(tail)
//step 2
tail = to_insert
I have seen a lot of implementations of DFS using a boolean variable named visited, which I don't wish to use in my code. While considering a scene where we have a Node class that holds the reference to left and right nodes corresponding to its children and data which can be any Object, can this method be applicable to Binary Trees to calculate dfs ? I have a scenario where I don't have a adjacency list or matrix.
Is the following code a good implementation of DFS ? Is the time complexity of the code O(n) ?
public void dfsForTree(BSTNode root) {
Stack<BSTNode> s = new Stack<BSTNode>();
BSTNode node;
if (root == null) {
return;
}
s.push(root);
while (!s.isEmpty()) {
node = s.pop();
System.out.println(node.getData());
if (node != null) {
if (node.getRight() != null) {
s.push(node.getRight);
}
if (node.getLeft != null) {
s.push(node.getLeft);
}
}
}
}
BSTNode class implementation:
public class BSTNode {
private BSTNode left;
private BSTNode right;
private int data;
/* Constructor */
public BSTNode(int n) {
left = null;
right = null;
data = n;
}
/* Function to set left node */
public void setLeft(BSTNode n) {
left = n;
}
/* Function to set right node */
public void setRight(BSTNode n) {
right = n;
}
/* Function to get left node */
public BSTNode getLeft() {
return left;
}
/* Function to get right node */
public BSTNode getRight() {
return right;
}
/* Function to set data to node */
public void setData(int d) {
data = d;
}
/* Function to get data from node */
public int getData() {
return data;
}
A sure tell of an iterative tree walk is it requires an "up" link on a node (or saves them) to be able to backtrack. You do just this - only saving not "up" links but directly next links to go after backtracking. On the other hand, there are no interdependencies between steps. See Is this function recursive even though it doesn't call itself? for how to distinguish iterative and disguised recursive.
Also see Iterative tree walking for an overview of the algorithms.
Now, for computational complexity. The principle can be found at Big O, how do you calculate/approximate it?.
You do:
process every node
exactly once
push & pop nodes from the stack
each node is also pushed and popped exactly once
So, indeed, it's O(N).
My tree nodes have the 3 string fields and 3 node fields which are left, middle and right.
One of the problems is that the method can only take string as a parameter
This is what I have
public TreeNode findNode(String name) {
TreeNode pointer = this.getRoot();
if (pointer.getName().equals(name))
return pointer;
if (pointer.getLeft() != null)
pointer = pointer.getLeft();
findNode(name);
if (pointer.getMiddle() != null)
pointer = pointer.getMiddle();
findNode(name);
if (pointer.getRight() != null)
pointer = pointer.getRight();
findNode(name);
return null;
}
This causes a stack overflow error because I just keep setting the pointer to root. But I have to start somewhere and my only parameters for the method can be name. I can't seem to see how to do this.
You can use a list as a parameter stack.
public TreeNode findNode(String name) {
List<TreeNode> stack = new ArrayList<TreeNode>();
stack.add(this.getRoot());
while (!stack.isEmpty())
{
TreeNode node = stack.remove(0);
if (node.getName().equals(name))
return node;
if (pointer.getLeft() != null)
stack.add(node.getLeft());
if (node.getMiddle() != null)
stack.add(node.getMiddle());
if (node.getRight() != null)
stack.add(node.getRight());
}
return null;
}
You can remove from the end of the list instead of the front of the list if you want to search depth-first.
Im guessing you cannot change the signature of this function. Have a helper function that takes in two parameters, (Node and name) that you call with root and name.
In all three cases (left, middle, right), you are calling findNode(name) but not for those objects, instead it is for this. That's why you get stack overflow.
Use an auxiliary method that takes in a TreeNode parameter in addition to the string:
public TreeNode findNode(String name) {
return auxFindNode(this.getRoot(), name);
}
private TreeNode auxFindNode(TreeNode node, String name) {
//perform your recursive traversal here
}
Your code as it stands will never work because you keep setting pointer to the root of the tree at the beginning of the method. So all your recursive calls start with the root of the tree.
If you prefer not to use another method, you can traverse the tree iteratively by using stack:
public TreeNode findNode(String name) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode foundNode = null;
while(!stack.empty() && foundNode == null) {
TreeNode node = stack.pop();
if(node.getName().equals(name)) {
foundNode = node;
} else {
if(node.getLeft() != null) {
stack.push(node.getLeft();
}
if(node.getMiddle() != null) {
stack.push(node.getMiddle());
}
if(node.getRight() != null) {
stack.push(node.getRight());
}
}
}
return foundNode;
}
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.
I am developing a binary search tree in java. But i am facing certain difficulties in it. Here is the code
class Node {
Node left, right;
Integer data;
Node(Integer d, Node left, Node right) {
this.data = d;
this.left = left;
this.right = right;
}
}
class BinaryTree {
Node root;
public BinaryTree(Node root) {
this.root = root;
}
void insert(int d)
{
if(root==null)
root= new Node(d, null, null);
insert(root,d);
}
void insert(Node root, int d) {
if (root == null) {
root=new Node(d,null,null);
} else if (d > root.data) {
insert(root.right, d);
} else if (d < root.data) {
insert(root.left, d);
}
}
void inorder(Node root) {
if (root != null) {
inorder(root.left);
System.out.println(root.data);
inorder(root.right);
}
}
}
public class BST {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
BinaryTree bt=new BinaryTree(null);
while (!(str = br.readLine()).equalsIgnoreCase("0")) {
bt.insert(Integer.parseInt(str));
}
bt.inorder(bt.root);
}
}
The problem here i am facing is as in java there is only pass by value. I am getting the root as null in every case except the first case in which i have passed the newly created root into it. Here when i am making a recursive call to the insert function by passing the value of either left or right of the root then in the new call the new root has been created if required for it but when the function gets over it's values are not reflected to the caller function's variable.
In short the problem is due to the call by value being followed by the java.
Can anyone please suggest the solution for this problem?
Your calls to insert(root.right/left, d) do not change the original right/left nodes if they are null, but simply make the method arguments point to a new variable (which, as you noticed, in Java won't change the original reference). Your change to the first root works because you call a different method, insert(int).
Have you considered making left and right BinaryTrees instead of Nodes? Also, instead of using "null", consider having an "empty" BinaryTree (with a null root and an isEmpty method).
Note that conceptually, left and right are trees, not nodes, so the design will be cleaner.
Example code. Untested but the idea should be right:
class Node {
BinaryTree left, right;
Integer data;
Node(Integer d, BinaryTree left, BinaryTree right) {
this.data = d;
this.left = left;
this.right = right;
}
}
class BinaryTree {
Node root;
// Empty tree
BinaryTree() {
this(null);
}
BinaryTree(Node root) {
this.root == root;
}
void insert(int d) {
if (this.root == null) {
// The tree was empty, so it creates a new root with empty subtrees
this.root = new Node(d, new BinaryTree(), new BinaryTree());
} else if (d > this.root.data) {
this.root.right.insert(d);
} else if (d < this.root.data) {
this.root.left.insert(d);
}
}
}
Notes:
I respected the style of your existing code.
This implementation will skip repeated elements.
Suggestions,
I wouldn't use an Integer if you mean to use an int value.
If you are reproducing code which is in the JVM already, I would read how the code works there first (and copy what you need)
When I have a bug in my code, I use the debugger to work out what is going wrong.
I start with a the simplest unit I can make which shows the problem, and fixes that simple situation.
I would post the simplest unit test, which anyone can reproduce, and what you see in the debugger here if it doesn't make any sense.
This doesn't really answer your question, but is too long for a comment. ;)