Java pass by value with recursion - java

The following is a simple implementation of Binary search tree using java. However, the code always outputs "BST empty!!" despite inserting elements. Where am I going wrong? I suspect I'm going wrong with recursion. Any help is greatly appreciated.
public class BinarySearchTree {
NODE root;
BinarySearchTree(){
root = null;
}
void insert(NODE nodeptr,int key){
if(root == null){
nodeptr = new NODE(key);
return;
}
if(nodeptr == null){
nodeptr = new NODE(key);
return;
}
if(key <= nodeptr.data){
insert(nodeptr.left,key);
}
else{
insert(nodeptr.right,key);
}
}
void inorder(NODE nodeptr){
if(nodeptr == null){
System.out.println("BST empty!!");
return;
}
inorder(nodeptr.left);
System.out.println(nodeptr.data + " ");
inorder(nodeptr.right);
}
/*driver program*/
public static void main(String args[]){
int[] a = {20,30,40,24,39};
BinarySearchTree bst = new BinarySearchTree();
for (int i: a){
bst.insert(bst.root,i);
}
bst.inorder(bst.root);
}
}
class NODE{
int data;
NODE left,right;
NODE(int data){
this.data = data;
left = null;
right = null;
}
}

Your insert method never assigns value to the root, so it remains null.
If I understand your code, your insert should look like this :
void insert(NODE nodeptr,int key){
if(root == null){
root = new NODE(key);
return;
}
if(nodeptr == null){
insert (root, key);
return;
}
if(key <= nodeptr.data){
if (nodeptr.left != null)
insert(nodeptr.left,key);
else
nodeptr.left = new NODE(key);
}
else{
if (nodeptr.right != null)
insert(nodeptr.right,key);
else
nodeptr.right = new NODE(key);
}
}
If the root is null, ignore the passed nodeptr and put key at the root of the tree.
If nodeptr is null, try to insert the new key starting at the root of the tree.
otherwise, once you find a null nodeptr.left or nodeptr.right, you must put the new key there, because if you make another recursive call, you would be passing a null Node to it, and the recursion would never end.

Expanding from Erans answer you could change it to:
public void insert(int key){
if(root == null){
root = new NODE(key);
return;
}
insert(root,key)
}
private void insert(NODE nodeptr,int key){
if(key <= nodeptr.data){
if(nodeptr.left == null){
nodeptr.left = new NODE(key)
}
else {
insert(nodeptr.left,key);
}
}
else{
if(nodeptr.right == null){
nodeptr.right = new NODE(key)
}
else {
insert(nodeptr.right,key);
}
}
}
Edit: As he has added his own code now its just a matter of what style you like better. A single method or two methods from which the public one has only one parameter.

I wanted my insert method something like this. Got it to working finally. Thank you all for your precious time.
NODE insert(NODE nodeptr,int key){
if(nodeptr == null){
nodeptr = new NODE(key);
}
else if(key <= nodeptr.data){
nodeptr.left = insert(nodeptr.left,key);
}
else{
nodeptr.right = insert(nodeptr.right,key);
}
return nodeptr;
}
I would call insert method from main something like this:
bst.root = bst.insert(bst.root,i);

Related

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 deletion method [duplicate]

I am trying to implement a remove method for the BST structure that I have been working on. Here is the code with find, insert, and remove methods:
public class BST {
BSTNode root = new BSTNode("root");
public void insert(BSTNode root, String title){
if(root.title!=null){
if(title==root.title){
//return already in the catalog
}
else if(title.compareTo(root.title)<0){
if(root.leftChild==null){
root.leftChild = new BSTNode(title);
}
else{
insert(root.leftChild,title);
}
}
else if(title.compareTo(root.title)>0){
if(root.rightChild==null){
root.rightChild = new BSTNode(title);
}
else{
insert(root.rightChild,title);
}
}
}
}
public void find(BSTNode root, String title){
if(root!= null){
if(title==root.title){
//return(true);
}
else if(title.compareTo(root.title)<0){
find(root.leftChild, title);
}
else{
find(root.rightChild, title);
}
}
else{
//return false;
}
}
public void remove(BSTNode root, String title){
if(root==null){
return false;
}
if(title==root.title){
if(root.leftChild==null){
root = root.rightChild;
}
else if(root.rightChild==null){
root = root.leftChild;
}
else{
//code if 2 chlidren remove
}
}
else if(title.compareTo(root.title)<0){
remove(root.leftChild, title);
}
else{
remove(root.rightChild, title);
}
}
}
I was told that I could use the insert method to help me with the remove method, but I am just not seeing how I can grab the smallest/largest element, and then replace the one I am deleting with that value, then recursively delete the node that I took the replacement value, while still maintaining O(logn) complexity. Anyone have any ideas or blatant holes I missed, or anything else helpful as I bang my head about this issue?
EDIT:
I used the answers ideas to come up with this, which I believe will work but I'm getting an error that my methods (not just the remove) must return Strings, here is what the code looks like, I thought that's the return statements??
public String remove(BSTNode root, String title){
if(root==null){
return("empty root");
}
if(title==root.title){
if(root.leftChild==null){
if(root.rightChild==null){
root.title = null;
return(title+ "was removed");
}
else{
root = root.rightChild;
return(title+ "was removed");
}
}
else if(root.rightChild==null){
root = root.leftChild;
return(title+ "was removed");
}
else{
String minTitle = minTitle(root);
root.title = minTitle;
remove(root.leftChild,minTitle);
return(title+ "was removed");
}
}
else if(title.compareTo(root.title)<0){
remove(root.leftChild, title);
}
else{
remove(root.rightChild, title);
}
}
public void remove (String key, BSTNode pos)
{
if (pos == null) return;
if (key.compareTo(pos.key)<0)
remove (key, pos.leftChild);
else if (key.compareTo(pos.key)>0)
remove (key, pos.rightChild);
else {
if (pos.leftChild != null && pos.rightChild != null)
{
/* pos has two children */
BSTNode maxFromLeft = findMax (pos.leftChild); //need to make a findMax helper
//"Replacing " pos.key " with " maxFromLeft.key
pos.key = maxFromLeft.key;
remove (maxFromLeft.key, pos.leftChild);
}
else if(pos.leftChild != null) {
/* node pointed by pos has at most one child */
BSTNode trash = pos;
//"Promoting " pos.leftChild.key " to replace " pos.key
pos = pos.leftChild;
trash = null;
}
else if(pos.rightChild != null) {
/* node pointed by pos has at most one child */
BSTNode trash = pos;
/* "Promoting " pos.rightChild.key" to replace " pos.key */
pos = pos.rightChild;
trash = null;
}
else {
pos = null;
}
}
}
This is the remove for an unbalanced tree. I had the code in C++ so I have quickly translated. There may be some minor mistakes though. Does the tree you are coding have to be balanced? I also have the balanced remove if need be. I wasn't quite sure based on the wording of your question. Also make sure you add a private helper function for findMax()
void deleteTreeNode(int data){
root = deleteTreeNode(root ,data);
}
private TreeNode deleteTreeNode(TreeNode root, int data) {
TreeNode cur = root;
if(cur == null){
return cur;
}
if(cur.data > data){
cur.left = deleteTreeNode(cur.left, data);
}else if(cur.data < data){
cur.right = deleteTreeNode(cur.right, data);
}else{
if(cur.left == null && cur.right == null){
cur = null;
}else if(cur.right == null){
cur = cur.left;
}else if(cur.left == null){
cur = cur.right;
}else{
TreeNode temp = findMinFromRight(cur.right);
cur.data = temp.data;
cur.right = deleteTreeNode(cur.right, temp.data);
}
}
return cur;
}
private TreeNode findMinFromRight(TreeNode node) {
while(node.left != null){
node = node.left;
}
return node;
}
To compare objects in java use .equals() method instead of "==" operator
if(title==root.title)
^______see here
you need to use like this
if(title.equals(root.title))
or if you are interesed to ignore the case follow below code
if(title.equalsIgnoreCase(root.title))
private void deleteNode(Node temp, int n) {
if (temp == null)
return;
if (temp.number == n) {
if (temp.left == null || temp.right == null) {
Node current = temp.left == null ? temp.right : temp.left;
if (getParent(temp.number, root).left == temp)
getParent(temp.number, root).left = current;
else
getParent(temp.number, root).right = current;
} else {
Node successor = findMax(temp.left);
int data = successor.number;
deleteNode(temp.left, data);
temp.number = data;
}
} else if (temp.number > n) {
deleteNode(temp.left, n);
} else {
deleteNode(temp.right, n);
}
}
I know this is a very old question but anyways... The accepted answer's implementation is taken from c++, so the idea of pointers still exists which should be changed as there are no pointers in Java. So every time when you change the node to null or something else, that instance of the node is changed but not the original one This implementation is taken from one of the coursera course on algorithms.
public TreeNode deleteBSTNode(int value,TreeNode node)
{
if(node==null)
{
System.out.println("the value " + value + " is not found");
return null;
}
//delete
if(node.data>value) node.left = deleteBSTNode(value,node.left);
else if(node.data<value) node.right = deleteBSTNode(value,node.right);
else{
if(node.isLeaf())
return null;
if(node.right==null)
return node.left;
if(node.left==null)
return node.right;
TreeNode successor = findMax(node.left);
int data = successor.data;
deleteBSTNode(data, node.left);
node.data = data;
}
return node;
}
All the links between the nodes are pertained using the return value from the recursion.
For the Depth First Post-Order traversal and removal, use:
/*
*
* Remove uses
* depth-first Post-order traversal.
*
* The Depth First Post-order traversal follows:
* Left_Child -> Right-Child -> Node convention
*
* Partial Logic was implemented from this source:
* https://stackoverflow.com/questions/19870680/remove-method-binary-search-tree
* by: sanjay
*/
#SuppressWarnings("unchecked")
public BinarySearchTreeVertex<E> remove(BinarySearchTreeVertex<E> rootParameter, E eParameter) {
BinarySearchTreeVertex<E> deleteNode = rootParameter;
if ( deleteNode == null ) {
return deleteNode; }
if ( deleteNode.compareTo(eParameter) == 1 ) {
deleteNode.left_child = remove(deleteNode.left_child, eParameter); }
else if ( deleteNode.compareTo(eParameter) == -1 ) {
deleteNode.right_child = remove(deleteNode.right_child, eParameter); }
else {
if ( deleteNode.left_child == null && deleteNode.right_child == null ) {
deleteNode = null;
}
else if ( deleteNode.right_child == null ) {
deleteNode = deleteNode.left_child; }
else if ( deleteNode.left_child == null ) {
deleteNode = deleteNode.right_child; }
else {
BinarySearchTreeVertex<E> interNode = findMaxLeftBranch( deleteNode.left_child );
deleteNode.e = interNode.e;
deleteNode.left_child = remove(deleteNode.left_child, interNode.e);
}
} return deleteNode; } // End of remove(E e)
/*
* Checking right branch for the swap value
*/
#SuppressWarnings("rawtypes")
public BinarySearchTreeVertex findMaxLeftBranch( BinarySearchTreeVertex vertexParameter ) {
while (vertexParameter.right_child != null ) {
vertexParameter = vertexParameter.right_child; }
return vertexParameter; } // End of findMinRightBranch

Binary Tree: Why Does One Insert Method Work and the Other Not

I just learned about binary trees and I tried to create an insert method. My first method did not work and I did a bit of tweaking. It now works but I do not understand why the previous method failed.
The method that does not work is:
if(root == null)
{
root = new Node(data);
}
else if(data < root.getData())
{
insertNode(root.getLeft(), data);
}
else
{
insertNode(root.getRight(), data);
}
The method that does work is:
if(data < root.getData())
{
if(root.getLeft() == null)
{
root.left = new Node(data);
}
else
{
insertNode(root.getLeft(), data);
}
}
else
{
if(root.getRight() == null)
{
root.right = new Node(data);
}
else
{
insertNode(root.getRight(), data);
}
}
Any explanations as to why this is the case? Because the way I see it, root should be equal to root.left, so setting root to a new Node should be the same as setting root.left/right to a new Node.
In your first method, you would give null into your insertNode method, but no reference pointer. Therefore you set root = new Node() in the insertNode method, but the parent node does not know any of this, it still points to null.
Since this is some very basic Java understanding, I recommend reading some articles about "java parameter passing" e.g. http://javadude.com/articles/passbyvalue.htm
Assuming that you call the method recursively, insertNode(root, data), you have to be sure that root is not null, which means executing root = new Node(data); creates an object whose visibility is limited to insertNode method.
If not, you can rewrite insertNode(data) to be non-recursive and create the root inside it if it is null.
public void insert(int data) {
if(root == null){
root = new Node(data);
}
else {
Node current = root;
Node previous;
String from;
while(current != null) {
previous = current;
if(data < current.getData()) {
current = current.left();
from = "left";
}
else {
current = current.right();
from = "right";
}
}
current = new Node(data);
if(from.equals("left")) {
previous.left() = current;
} else {
previous.right() = current;
}
}
}

Implementing a Binary Tree

I'm trying to implement a binary tree, but its just not taking the root. Any ideas? It looks like the root should be inserting fine, but I'm just getting a null when I print it. Am I trying to add only temporary nodes to the tree that don't "stick"?
public class tree {
public static void main(String args[]){
Treeb tree = new Treeb();
tree.add(10);
tree.add(20);
tree.add(2);
tree.add(6);
tree.printTree();
}
}
class Node{
int data;
Node left;
Node right;
public Node(int data){
this.data = data;
left = null;
right = null;
}
Node getLeft(){
return left;
}
Node getRight(){
return right;
}
}
class Treeb{
Node root;
Treeb(){
root = null;
}
void add(int n){
addNode(n, root);
}
void addNode(int n, Node vert){
if(vert == null){
vert = new Node(n);
}
else if(vert.left.data < n){
if(vert.left == null){
vert.left = new Node(n);
}
else{
addNode(n, vert.left);
}
}
else if(vert.right.data >= n){
if(vert.right == null){
vert.right = new Node(n);
}
else{
addNode(n,vert.right);
}
}
}
void printTree(){
if(root != null){
printChild(root);
}
System.out.println(root);
}
void printChild(Node leaf){
System.out.print(leaf.data);
if(leaf.left != null){
printChild(leaf.getLeft());
}
if(leaf.right != null){
printChild(leaf.getRight());
}
}
}
You are assigning vert a new reference, but not root, that's why it stays null.
Your method addNode(int, Node) isn't working.
First:
if(vert == null){
vert = new Node(n);
}
You're assigning the new node to a local variable. Thus, the new Node gets discarded at the end of the method.
Second:
}
else if(vert.left.data < n){
// code
}
else if(vert.right.data >= n){
vert.left and vert.rightcan be null, so you would get an NPE when vert is not null.
getLeft() and getRight() can (and will) return null sometime. You should make sure in your printChild() that leaf itself is not null. (You're probably getting NPE in if(leaf.left != null) since leaf is null), you might also want to reconsider your tree construction again, root is null in your case.

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