This question already has an answer here:
How to implement a generic in-order traversal in java binary tree?
(1 answer)
Closed 2 years ago.
I have implemented two functions in this code first is inserting elements in a binary tree and the other is In-order traversal .Please help how to call the In-order function ,as the function is asking for a argument of type node which is needed to be given but I am new to this to got struck what to pass in it.
import java.util.Scanner;
class BinaryTree {
Node root;
class Node {
int data;
Node leftChild;
Node rightChild;
public Node(int data) {
this.data = data;
leftChild = null;
rightChild = null;
}
}
public Node insert(Node current, int data) {
if (current == null) {
return new Node(data);
} else if (data < current.data) {
current.leftChild = insert(current.leftChild, data);
} else if (data > current.data) {
current.rightChild = insert(current.rightChild, data);
}
return current;
}
public void add(int data) {
root = insert(root, data);
}
void inorder(Node current) {
if (current != null) {
inorder(current.leftChild);
System.out.println(current.data);
inorder(current.rightChild);
}
}
public static void main(String[] args) {
// Write your code here
BinaryTree bt = new BinaryTree();
bt.add(2);
bt.add(1);
bt.add(3);
bt.add(4);
bt.add(7);
bt.add(8);
bt.inorder();
}
}
You want to pass in the root of your binary tree, which is stored in the root member variable in your BinaryTree class. So you want to do:
bt.inorder(bt.root);
This, with the rest of your code unchanged, gives the following result:
1
2
3
4
7
8
Since you are calling a method in the same class that has the data you need to pass to that method, you could also add a new method to your class that does the same thing without having to pass in any data. You could either use the same name as the method you already have, or some other name. Here's the method using the same name:
void inorder() {
inorder(root);
}
If you add this method to your BinaryTree class, your code will work with no other changes, and will give the same result.
Related
I am calling a constructor in a method to insert new nodes.While I am adding new node default constructor is creating new node with default values . I want to just insert values using insert method as in below code . Is there any way I may avoid first node being default.
class Node {
Node right, left;
int data = 0;
Node() {
}
Node(int data) {
this.data = data;
}
public void insert(int value) {
if (value <= data) {
if (left == null) {
left = new Node(value);
} else {
left.insert(value);
}
} else {
if (right == null) {
right = new Node(value);
} else {
right.insert(value);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Node new_node=new Node();//creating first node with 0 value
new_node.insert(5);
new_node.insert(4);
new_node.insert(9);
new_node.insert(23);
new_node.insert(70);
new_node.display();
}
}
You could use the first value as the first element:
Node new_node = new Node(5); // create 1st node with 1st value
Or you could define a new default constructor with a value that you don't expect to be in the list (let's say -1), but you'd have to be careful about this element in your list that is not really part of the list, and that makes implementing other operations trickier:
Node() { data = -1; }
But all this is symptom of a bigger problem: you shouldn't handle the head of your list in the Node class. It'd be better to create a new class, let's call it MyList and define a Node head attribute on it, and all insert/update/delete/search operations should be implemented on that class.
It's important to keep the head separate, because there will be operations that modify the head. For example, your insert() method doesn't consider the case when the node to insert should go at the beginning of the existing list.
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).
This is my implementation of binary Node class:
public class BinaryNode{
int element;
BinaryNode left;
BinaryNode right;
BinaryNode(int theElement,BinaryNode lt,BinaryNode rt){
element=theElement;
left=lt;
right=rt;
}
BinaryNode(int theElement){
this(theElement,null,null);
}
}
Here's my insert method in binaryTree class
public class BinaryTree {
private BinaryNode root;
public BinaryTree(){
root= null;
}
BinaryTree(int nodeValue){
root=new BinaryNode(nodeValue);
}
public void insert(BinaryNode node,int x){
if(node==null){
node=new BinaryNode(x);
}
else if(node.element<x){
insert(node.left,x);
}
else if (node.element>x){
insert(node.right,x);
}
else
System.out.println("Duplicates not allowed");
}
I have two questions.
1) how can I insert elements to this BinaryTree class and thereby create a tree.
public static void main (String args[]){
BinaryTree t=new BinaryTree();
t.insert(t.root,5);
}
But after inserting 5 how can I call on insert method to add integers like 10,12,78,...
2) Also when I looked up at some code for inserting to binary trees I found this code .
/**
Inserts the given data into the binary tree.
Uses a recursive helper.
*/
public void insert(int data) {
root = insert(root, data);
}
/**
Recursive insert -- given a node pointer, recur down and
insert the given data into the tree. Returns the new
node pointer (the standard way to communicate
a changed pointer back to the caller).
*/
private Node insert(Node node, int data) {
if (node==null) {
node = new Node(data);
}
else {
if (data <= node.data) {
node.left = insert(node.left, data);
}
else {
node.right = insert(node.right, data);
}
}
return(node); // in any case, return the new pointer to the caller
}
The code looks similar to mine, but why use a helper method insert() as well?What's the purpose of it?
Can someone please solve help me to understand this
Inserting an element in a binary tree should require only the tree and the element as input. The tree itself should determine which node should be updated. This is achieved by means of a recursive function which starts from root: this is the helper function, which acts on a node.
The first problem is that you won't be able to access t.root directly because it's private. You either need a getter
public BinaryNode getRoot() {
return this.root;
}
or make root public
The helper method is used, so the new root of the BinaryTree can be determined. And because the root should not be returned to the caller. But since it's easier to insert something into a binary tree recursivley the private method is used to do that.
You would use the methods like this:
public static void main(String[] args) {
BinaryTree t = new BinaryTree(5); //Create a new tree with one item
t.insert(12); // Assuming that you used the implementation with the helper method
t.insert(3); //
t.insert(t.getRoot(),12); // Assuming you used your implementation
t.insert(t.getRoot(),3); //
}
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;
}
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. ;)