Treenode data structure explanation - java

In the following program,
what does this mean left.parent = this; I know it says make parent of left child to be 'this' but what exactly is this. this refers to current instance method right? but can anyone explain a bit better.
public class TreeNode {
public int data;
public TreeNode left;
public TreeNode right;
public TreeNode root;
private int size = 0;
public TreeNode(int d) {
data = d;
size = 1;
}
public void setLeftChild(TreeNode left) {
this.left = left;
if (left != null) {
left.root= this;
}
}
Would the same function setLeftChild above be represented like the function below:
void setLeftChild(TreeNode node)
{
if(root == null)
{
this.root = node;
}
else
{
this.left = node;
}
}
Is the implementation correct? first and 2nd?
If not then what is wrong with the 2nd implementation? and vice versa
What is the difference between first and 2nd implementation?

No the bottom code is not correct. In the bottom implementation what you do is you make the left child node actually the parent node of your class. If the node you are in already is not the root node then the left child is set correctly, but the left child does not get its parent set correctly.
The image below is the result of executing the code on the bottom
The image below is the result of executing the top block (which is correct)

Assuming you did
TreeNode a = new TreeNode (1);
At this time a's left, right and root are null
if you did
TreeNode b = new TreeNode (b);
a.setLeftChild (b);
then now a's right and root are still null but left is b
and b's root is now a

this is a reference to current object
http://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html

Related

Implementation of DFS using iterative approach in java

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).

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

Binary Tree Creation

I am attempting to create a binary tree from an input of 0's and 1's. For example if the input is 11010010 then the tree that is outputted would have 1 as the root. 2 would be the left child of 1 and 4 would be the right child. 2 would have a right child and it would be 3. That is the end of the tree. As the tree is traversed in preorder, the numbers 1-n (n being the number of 1's in the input) are assigned to the nodes that are visited. A 1 means that the root has children. For example the first 1 means that the root is visited and a 1 is placed as the root. The second 1 means that the root has a left child and a 2 is placed there. The 0 after that means it does not have a left child. The next 1 means that it does have a right child and the 3 is placed there, etc. I am confused on how this tree is created. I understand traversing a tree after it has been created but not how to create a tree by traversing it. Any help would be appreciated.
package tree;
import java.io.*;
public class BinaryTree<ArrayList> implements Serializable
{
private static final long serialVersionUID = 1L;
protected static class Node<ArrayList> implements Serializable
{
private static final long serialVersionUID = 1L;
protected int data;
protected Node<ArrayList> left;
protected Node<ArrayList> right;
public Node(int data)
{
this.data = data;
left = null;
right = null;
}
public boolean isLeft()
{
return (left == null);
}
}
protected Node<ArrayList> root;;
public BinaryTree(int x)
{
Node<ArrayList> node = new Node<ArrayList>(x);
this.root = node;
}
public boolean isLeft()
{
return(root.left == null);
}
public void addLeft(int m, BinaryTree.Node<ArrayList> node)
{
root = new Node<ArrayList>(m);
node.left = root;
}
public void preorder(Node<ArrayList> temp)
{
if (temp!=null)
{
System.out.println(temp.data);
preorder(temp.left);
preorder(temp.right);
}
else
return;
}
}
It sounds like you're constructing a tree in a default, breadth-first manner, assigning values to each node based off of what the string says.
If it helps, first turn the string into an ArrayList<int> of values to put in nodes - For example, 11010010 would become {1, 2, 4, 7}, the indices of each set 1 in the string.
Now, we have to construct the tree - but we'll always construct the tree in the exact same way, called breadth first because you fill shallow levels completely before going deep. We make a node, then tell it 'make your left node, then make your right node, then tell your left node to do this, then tell your right node to do this'. (This is as opposed to depth first, where you make your left node, tell your left node to make nodes, then make your right node and tell your right node to make nodes)
So you'd have a recursive method something like this pseudocode:
void continueTree(ArrayList<int> numbers)
{
if (numbers.count() == 0) return;
this.left = new Node(numbers.get(0));
numbers.remove(0);
if (numbers.count() == 0) return;
this.right = new Node(numbers.get(0));
numbers.remove(0);
this.left.continueTree(numbers);
this.right.continueTree(numbers);
}

JAVA: Problems creating a Binary Tree

Ok, here is my code. I am trying to practice with Binary Trees. Why can't my size() method access the root node of my binary tree?
Also my root.left, and root.right assignments do not work.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.lang.*;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
System.out.println(bTree.size());
}
}
//Building Binary Trees
class bTree {
static class Node { //remember to initilize a root
String value;
Node left, right;
Node root = new Node("ROOT");
Node lefty = new Node("LEFT0");
Node righty = new Node("RIGHT0");
root.left = lefty;
root.right = righty;
Node(String value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
Node(String value) //THIS IS A SIBLING CONSTRUCTOR
{
this(value, null, null);
}
}
public static int size() //Public | sibling constructor
{
System.out.println("Debug0");
System.out.println(root.value);
return size(root);
}
//This method will find the size of a node
private static int size(Node r) //using recursion
{
if (r == null) {
return 0;
} else {
return 1 + (size(r.left) + size(r.right));
}
}
}
Any help would be much appreciated, I have a final tomorrow on this information!
Sam
As your comment in your code says:
//remember to initialize a root
You didn't do that (at least in your sample).
The only variable root is defined in the sub-class of bTree, and is not directly available to the size() method.
size() should read:
public static int size() {
System.out.println("Debug0");
System.out.println(Node.root.value);
return size(Node.root);
}
root is scoped to your static Node class. size() is outside of that scope, so it can't access root.
Something like this would work:
public class TreeTraversal {
class Node {
String value;
Node left, right;
public Node(String value) {
this.value = value;
}
}
public static void main(String[] args) {
// Construct a binary tree
Node root = new Node("root");
Node child = new Node("child 1");
root.left = child;
child = new Node("child 2");
root.right = child;
// Find its size
System.out.println(size(root));
}
private static int size(Node root) {
return sizeRec(root);
}
private static int sizeRec(Node r) {
if (r == null) {
return 0;
} else {
return 1 + (sizeRec(r.left) + sizeRec(r.right));
}
}
}
This is a sort of condensed version of a binary tree. I have attempted to strip away all unnecessary stuff (nested classes, extra imports, static methods except for main, nested static classes, recursive object construction).
public class Node {
private String value;
private Node left;
private Node right;
public Node(String value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
public int size() {
int ret = 1;
if (left != null) ret += left.size();
if (right != null) ret += right.size();
return ret;
}
public static void main(String args[]) {
Node tree = new Node("root",
new Node("left", null, null),
new Node("right", null, null));
// expect 3
System.out.println(tree.size());
}
}
Now, notice a few things:
A tree is just a Node.
size is an instance method of Node. (my recursive structure is a bit different than if it were static, in particular, where the null checks go)
The only members of Node are value, left, and right. I don't actually use value for anything, and without an accessor, would have some difficulty doing so.
My assignment to left and right is in the constructor, not floating freely in the class declaration.
Start with something simple.
From here, you could declare a class BTree (But why? is it just to practice having nested classes?). It would contain a Node named root and a size method that simply calls root's size method.
You could declare a nice constructor that doesn't require children. Then you might also want to provide methods on a Node to set the children after construction.
Relax and focus on the specific problems that are going to be on your final. Find a different practice problem and try again. Eat healthy and get some rest. Then, good luck on your final.
To access root in bTree, you need to write Node.root.
Your Node is a top level class (read up about static inner classes). Hence your code
public static int size() //Public | sibling constructor
{
System.out.println("Debug0");
System.out.println(root.value);
return size(root);
}
won't work, you need to create a root Node.
Furthermore, I think your definition
Node root = new Node("ROOT");
is not necessary in Node, unless you want a reference back to the root node from every node, which I find a bit ugly :-0
Finally, why do you use the class bTree at all? You can identify a Node n with the tree that is rooted at n. I.e. put the size method within node.

Java Binary Search Tree implementation problem.!

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. ;)

Categories

Resources