binarysearch tree tree.root returns null - java

I found binary search tree insertion java code on the website,
https://www.geeksforgeeks.org/binary-search-tree-set-1-search-and-insertion/
and part of the code is like below,
if (root == null) {
root = new Node(key);
return root;
}
and I thought we don`t need any return statement because root itself is reference type(Node), so updating root is enough.
so I changed the code like this.
class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
Node root;
BinarySearchTree() {
root = null;
}
void insert(int key) {
insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
void insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
}
if (key < root.key)
insertRec(root.left, key);
else if (key > root.key)
insertRec(root.right, key);
}
// Driver Program to test above functions
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
tree.insert(50);
tree.insert(20);
System.out.println(tree.root);
}
}
but tree.root returns null.
why is this happening?

root = new Node(key); updates a local variable, it doesn't update the root of the tree (this.root), and it shouldn't. Therefore this assignment doesn't update the tree.
When you return the newly created Node (as in the original code that you changed did), you can assign it to be either the root of the tree (as the original code did with root = insertRec(root, key);) or the left or right child of an existing tree node (as the original code did with root.left = insertRec(root.left, key); or root.right = insertRec(root.right, key);). That's how the tree is updated.
EDIT: Java is a pass by value language, not pass by reference. When you pass a variable to a method, that method can't change the value of the passed variable. If you pass a variable whose value is null to a method, and that method assigns a value to it, the variable will still contain null once the method returns.

Like others already have pointed out, you need to update your root every time you insert an element.
Just return the value of root and update your global root for the tree.
Node insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
return root;
}
if (key < root.key)
root.left = insertRec(root.left, key);
else
root.right = insertRec(root.right, key);
return root;
}
Finally, update your global root.
tree.root = tree.insert(50);
tree.root = tree.insert(20);
Full code:
class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
Node root;
BinarySearchTree() {
root = null;
}
Node insert(int key) {
return insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
return root;
}
if (key < root.key)
root.left = insertRec(root.left, key);
else
root.right = insertRec(root.right, key);
return root;
}
// Driver Program to test above functions
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
tree.root = tree.insert(50);
tree.root = tree.insert(20);
System.out.println(tree.root.key);
}
}

/* A recursive function to insert a new key in BST */
void insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
}
}
It is called "shadows effect".
That mean your root note from parent class is shadowed by root node in your method.
To fixed it use "this.root" to reference to parent class and initialized the object.
More information : read "Shadowing" in the article. It explained very well.
http://ocpj8.javastudyguide.com/ch03.html

In your constructor you don't initialise a rootNode. Your key is also not transformed in a Node and you don't set your inserted Node to a left or right node. Also you don't do anything with a node that is equal to the current node you traverse.

Related

Construction tree

I wrote a tree construction method. I don't see any errors when running it. However, when I'm testing the tree if it is symmetric or not and should return false (for input: [1,2,2,4,4, null, 6]) This means that I am putting root node as 1, second level: 2,2 third level: 4, 4, null, 6. It is returning true. I'm not sure what's wrong? I'm sure that my symmetric function is correct, I just don't know what's wrong with my tree construction? I tried debugging and I saw all the values in the array were implemented in the construction. Can someone let me know what's going on?
public class isSymmetric {
public static class TreeNode {
public int key;
public TreeNode left;
public TreeNode right;
public TreeNode(int key) {
this.key = key;
this.left = this.right = null;
}
}
public boolean symmetric(TreeNode root) {
...
}
//Tree test cases
public static TreeNode construction(Integer[] array) {
//use level order traversal to construct a tree
TreeNode root = new TreeNode(array[0]);
return constructionhelp(array, root, 0);
}
public static TreeNode constructionhelp(Integer[] array, TreeNode root, int i) {
if (root == null) {
return null;
}
if (i < array.length) {
root = new TreeNode(array[i]);
root.left = constructionhelp(array, root.left, 2*i+1);
root.right = constructionhelp(array, root.right, 2*i+2);
}
return root;
}
public static void main(String[] args) {
isSymmetric s = new isSymmetric();
Integer a[] = {1,2,2,4,4,null,6};
TreeNode roota = construction(a);
System.out.print(s.symmetric(roota));
}
}
//returning true;
What happens:
root = new TreeNode(array[i]); // you create new tree node instance
root.left = constructionhelp(array, root.left, 2*i+1); // root.left is null
root.right = constructionhelp(array, root.right, 2*i+2) // root.right is null
so after you call your constructionhelp again, you pass null as an argument of the node.
-> null is returned.
-> your tree is only the root.

Binary Search Tree for employee manager search

I want to write a java program to arrange the given employee ID in a Binary Search Tree format and then find the immediate manager of any given employee in the organization.
Employee Binary Tree:
Input Format
The first line should contain the number of employees "n" to be inserted in the Tree
The second line should contain the employee ID for which we need to find the immediate manager.
The next "n" lines should contain the employee IDs to form the binary search Tree.
Sample:
Below is the code with which I have intialized the tree successfully. I need help on how to search the parent node for a given child node.
import java.util.Scanner;
class BinarySearchTree {
/* Class containing left and right child of current node and key value*/
class Node {
int data;
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
// Root of BST
Node root;
// Constructor
BinarySearchTree() {
root = null;
}
// This method mainly calls insertRec()
void insert(int key) {
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
// This method mainly calls InorderRec()
void inorder() {
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root) {
if (root != null) {
inorderRec(root.left);
System.out.println(root.key);
inorderRec(root.right);
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
//int sch = sc.nextInt();
for (int i=0;i<num;i++) {
tree.insert(sc.nextInt());
}
tree.inorder();
}
}
When you write a recursive method, the first thing you need is a condition that terminates the recursion. In your case there are two conditions, as follows.
You find the employee that you are searching for.
You reach the end of the tree.
The recursion needs to terminate if either of the above conditions is true. In your case, terminating the recursion means the method must return a value.
If the terminating condition is not true, the method needs to call itself but with different values for the method parameters.
Here is my recursive search method. More explanation appears after the code.
int search(int employee, int manager, Node node) {
if (node != null) {
if (employee == node.key) {
return manager;
}
manager = node.key;
if (employee < node.key) {
return search(employee, manager, node.left);
}
else {
return search(employee, manager, node.right);
}
}
else {
return -1;
}
}
The method parameters are as follows:
employee - the employee to search for
manager - the manager of the next parameter
node - a node in the tree that will be checked to see if its key is the employee we are searching for
We start searching at the root of the tree and traverse down through the tree nodes. Hence the initial call to the method, which would probably be in method main() would be:
tree.search(sch, -1, tree.root)
According to your sample data, sch is 55. Note that in the initial call, the manager is -1 since the root of the tree does not have a manager. So if sch equals the root key, the method will return -1.
Since we know that the key in the left child of a node is lower and the right child's key is higher, we don't have to search every node. So the method calls itself with the relevant child node. Also we save the current key because if the child node's key is the one we are searching for, then this node's key is the manager.
If the node parameter in method search() is null, that means we have reached the end of the tree which means we have not found the value we are searching for. The value -1 (minus one) is a convention for a value that indicates that the search failed. Method indexOf() in class String is an example of a method also using that convention.
Finally, I used the code you posted in your question. I only added the above method as well as a call to that method from method main(). I added the initial call to method search() as the last line in method main().
For completeness, here is the entire code:
import java.util.Scanner;
public class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
// Root of BST
Node root;
// Constructor
BinarySearchTree() {
root = null;
}
// This method mainly calls insertRec()
void insert(int key) {
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
// This method mainly calls InorderRec()
void inorder() {
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root) {
if (root != null) {
inorderRec(root.left);
System.out.println(root.key);
inorderRec(root.right);
}
}
// The method I added.
int search(int employee, int manager, Node node) {
if (node != null) {
if (employee == node.key) {
return manager;
}
manager = node.key;
if (employee < node.key) {
return search(employee, manager, node.left);
}
else {
return search(employee, manager, node.right);
}
}
else {
return -1;
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int sch = sc.nextInt();
for (int i = 0; i < num; i++) {
tree.insert(sc.nextInt());
}
tree.inorder();
System.out.printf("Manager is %d%n", tree.search(sch, -1, tree.root)); // changed this line to print only manager.
}
}

By using this BST insertion method I have only root as output,why?

I am trying to insert in a binary search tree using recursion and then print it preorderly using this specific code, but I have only root as output,why?Is this because each time stack(after each call) is popping off thus removing new nodes?(This is a java code)
class node{
int data;
node left;
node right;
node(int key){
data = key;
left = right = null;
}
}
class bst{
node root;
node temp;
node last;
bst(){
root = null;
}
bst(int key){
root = new node(key);
}
void Insert(node r,int value){
temp = r;
if(temp == null){
if(root == null){
root = new node(value);
root.data = value;
return;
}
temp = new node(value);
temp.data = value;
return;
}
else{
if(value > temp.data){
Insert(temp.right,value);
return;
}
else{
Insert(temp.left,value);
return;
}
}
}
}
class test{
static void in_order(node root){
if(root == null){
return;
}
in_order(root.left);
System.out.println(root.data+" ");
in_order(root.right);
}
public static void main(String[] args){
bst tree = new bst();
tree.Insert(tree.root,45);
tree.Insert(tree.root,39);
tree.Insert(tree.root,12);
tree.Insert(tree.root,59);
test.in_order(tree.root);
}
}
The reason you are only getting a single integer for an output is because the first Insert call correctly adds the element to the tree, but subsequent calls fail because you overwrite the data member temp to null when you recursively insert to the left or right. Thus the second branch of your first if statement never gets executed.
You don't actually need the variable temp here. A common convention is to have a private, recursive member function that takes the root of the tree as a parameter returns the modified tree, and assign the return value to root in a public member function.
public void Insert(int value) {
root = Insert(root, value);
}
private node Insert(node r, int value) {
if (r == null) {
r = new node(value);
}
else if (value > r.data) {
r.right = Insert(r.right, value);
}
else {
r.left = Insert(r.left, value);
}
return r;
}
This means that you only have to call it like tree.Insert(x).

Binary Search tree won't add new nodes?

I am trying to write a recursive method to add a node to a binary search tree (that does not allow duplicates). For some reason, the method only works when the tree is empty, otherwise it prints out "Duplicate" (even if it is not a duplicate). I am new to programming and would appreciate help and tips to fix this. Thank you.
//add new node to the tree
public void add(int data) {
Node<Integer> newNode = new Node<>(data); //create new node with the data
//if the tree is empty, the newNode becomes the root
if (size() == 0) {
root = newNode;
return;
}
//otherwise, check if node should be placed to right or left
add(data, root);
}
private void add(int data, Node<Integer> node) {
//base case - found an empty position
if (node == null) {
node = new Node<Integer>(data);
}
if (data < node.data) {
add(data, node.left);
}
else if (data > node.data) {
add(data, node.right);
}
else if (data == node.data) {
System.out.println("Duplicate. This value cannot be added to the tree.");
}
}
When your tree is empty, the node is added properly to it. The first add(int data) function is fine.
The problem exists with the second add(int data, Node<Integer> node) function. In case if the tree already has an element, this method is called. If the node passed is either greater or lesser than the value passed then the function is called again with either the left or right child of the current node. This value might be (will eventually be) null. That leads to creation of a node in the base case of your method which leads to the satisfaction of this data == node.data condition as the node was indeed created with the data value. Hence you get the error message.
In order to fix this, the second function can be altered as below :
private void add(int data, Node<Integer> node) {
if (data < node.data) {
if (node.left != null) {
add(data, node.left);
} else {
node.left = new Node<>(data);
}
}
else if (data > node.data) {
if (node.right != null) {
add(data, node.right);
} else {
node.right = new Node<>(data);
}
add(data, node.right);
}
else if (data == node.data) {
System.out.println("Duplicate. This value cannot be added to the tree.");
}
}
See that the base case has been removed. If ever encountered the base case does not provide us with a reference to any tree node. Hence addition of data to the tree is impossible (the node argument must never be null).
Also, the code adds data as a child to node if the child is null. This guarantees that the method is not recursively with a null node argument and adds data to its rightful place more importantly.
At the end of the recursion you are not returning the actual root of the BST. "root" object that you have it is pointing to the last inserted node. So every time you are trying to insert the same value it will be inserted after the last inserted node which have the same value. Here is my implementation:
class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
Node root;
BinarySearchTree() {
root = null;
}
void add(int data) {
root = add(root, data);
}
Node add(Node root, int data) {
if (root == null) {
root = new Node(data);
return root;
}
if (data < root.key)
root.left = add(root.left, data);
else if (data > root.key)
root.right = add(root.right, data);
else if( data==root.key) {
System.out.println("Duplicate. This value cannot be added to the tree.");
}
return root;
}
void inorder() {
inorderRec(root);
}
void inorderRec(Node root) {
if (root != null) {
inorderRec(root.left);
System.out.println(root.key);
inorderRec(root.right);
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
tree.add(50);
tree.add(30);
tree.add(20);
tree.add(20);
// print inorder traversal of the BST
System.out.println("Inorder traversal");
tree.inorder();
tree.add(40);
tree.add(40);
tree.add(70);
tree.add(60);
tree.add(80);
System.out.println("Inorder traversal");
// print inorder traversal of the BST
tree.inorder();
}
}

Recursive Binary Search Tree Insert

So this is my first java program, but I've done c++ for a few years. I wrote what I think should work, but in fact it does not. So I had a stipulation of having to write a method for this call:
tree.insertNode(value);
where value is an int.
I wanted to write it recursively, for obvious reasons, so I had to do a work around:
public void insertNode(int key) {
Node temp = new Node(key);
if(root == null) root = temp;
else insertNode(temp);
}
public void insertNode(Node temp) {
if(root == null)
root = temp;
else if(temp.getKey() <= root.getKey())
insertNode(root.getLeft());
else insertNode(root.getRight());
}
Thanks for any advice.
// In java it is little trickier as objects are passed by copy.
// PF my answer below.
// public calling method
public void insertNode(int key) {
root = insertNode(root, new Node(key));
}
// private recursive call
private Node insertNode(Node currentParent, Node newNode) {
if (currentParent == null) {
return newNode;
} else if (newNode.key > currentParent.key) {
currentParent.right = insertNode(currentParent.right, newNode);
} else if (newNode.key < currentParent.key) {
currentParent.left = insertNode(currentParent.left, newNode);
}
return currentParent;
}
Sameer Sukumaran
The code looks a little confusing with overloaded functions. Assuming member variables 'left' and 'right' to be the left child and right child of the BSTree respectively, you can try implementing it in the following way:
public void insert(Node node, int value) {
if (value < node.value)
{
if (node.left != null)
{
insert(node.left, value);
}
else
{
node.left = new Node(value);
}
}
else if (value > node.value)
{
if (node.right != null)
{
insert(node.right, value);
}
else
{
node.right = new Node(value);
}
}
}
........
public static void main(String [] args)
{
BSTree bt = new BSTree();
Node root = new Node(100);
bt.insert(root, 50);
bt.insert(root, 150);
}
You should have a look to this article. It helps to implement a tree structure and search, insert methods:
http://quiz.geeksforgeeks.org/binary-search-tree-set-1-search-and-insertion/
// This method mainly calls insertRec()
void insert(int key) {
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
You can use standard Integer (wrapper for primitive int) object instead of creating a new object type Node. On latest java Integer/int auto-boxing is supported. Hence your method insertNode(int key) can take in Integer argument too (ensure it is not null).
EDIT: Pls ignore above comment. I did not understand your real question. You will have to overload insertNode(). I think you are right.
but where is temp when you insertNode?? With your current implementation temp is lost if root is not null.
I think you want something like
root.getLeft().insertNode(temp);
and
root.getRight().insertNode(temp);
i.e. To insert the new Node (temp) to either the left or the right subtree.

Categories

Resources