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();
}
}
Related
I'm trying to insert elements into binary tree, if the element is inserted it should return true and if the element is already in the tree it should return false.
Here is what i did, It doesn't give me any error message but it only returns true for the first element inserted and for the rest of them false even if they are not the same as the first element.
public static class Node {
int data;
Node left;
Node right;
Node(int d)
{data=d;
left=null;
right=null;}
}
static class BTree{
Node root;
}
static boolean insert(BTree t,int data) {
Node newNode=new Node(data);
if (t.root==null) {
t.root=newNode;
return true;
}
else {
while (t.root.data!=data) {
if (t.root.data>data)
{t.root=t.root.left; insert(t, data);}
else if (t.root.data<data)
{t.root=t.root.right; insert(t, data);}}
return false;
}
}
Your code is modifying t.root when the tree is not empty. This is wrong. During the decent through the tree, the root reference should not be changed.
Secondly, your algorithm is using both iteration (while) and recursion. But these are alternatives that you should not combine: choose either the iterative version or the recursive version.
Since your function takes a BTree instance, and there is only one such instance at play, a recursive implementation would need a different function; one that takes a Node type as argument.
Here I will just stick to the iterative idea and remove the recursion. Use a separate variable for traversing down the tree:
else {
Node node = t.root;
while (node.data != data) {
if (node.data > data) {
if (node.left == null) {
node.left = newNode;
return true;
}
node = node.left;
} else if (node.data < data) {
if (node.right == null) {
node.right = newNode;
return true;
}
node = node.right;
}
}
return false;
}
I'm working on a binary search tree where i have to delete a node. The node has already been found, so i don't need to traverse and find the specific node. All i need is to delete a node, which is taken as an arguement.
I have started the the node remove method and currently only done how to delete a node if it has no children or is a leaf node. How do i implement a java code which will delete if it has 1 children or a parent?
my current remove method:
public void removeHelper(Node focus){
if(focus.leftChild == null && focus.rightChild == null){
focus = null;
}
// if the node has 1 child
// if the node has 2 children
}
You need to travel down the tree, because you will need to replace the root field, or either the leftChild or rightChild of the parent node.
To remove a node that has both leftChild and rightChild not null, you can replace the node with either the rightmost node of the left subtree, or the leftmost node of the right subtree.
In this example, I assume that the methods are in a class (Tree?) that have a Node field called root, and that the Nodes have a field value that is a Comparable:
public void remove(Node focus) {
root = removeHelper(root, focus);
}
public static Node removeHelper(Node root, Node focus) {
if (root == null) {
return null;
} else if (root == focus) {
if (focus.leftChild == null) {
return focus.rightChild;
} else if (focus.rightChild == null) {
return focus.leftChild;
} else {
Node node = removeLeftMostOfRight(focus);
node.leftChild = focus.leftChild;
node.rightChild = focus.rightChild;
return node;
}
} else {
int r = focus.value.compareTo(root.value);
if (r < 0) {
root.leftChild = removeHelper(root.leftChild, focus);
} else {
root.rightChild = removeHelper(root.rightChild, focus);
}
return root;
}
}
private static Node removeLeftMostOfRight(Node focus) {
Node node = focus.rightChild;
if (node.leftChild == null) {
focus.rightChild = node.rightChild;
} else {
Node prev;
do {
prev = node;
node = node.leftChild;
} while (node.leftChild != null);
prev.leftChild = node.rightChild;
}
return node;
}
Note that in languages like C/C++ you can have pointers to pointer, that allow a much simpler and more efficient implementation of binary trees.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am getting red X's in my code for the closing } I have. They all look fine to me the IDE insists that I am wrong. I'm not sure why this is incorrect. Could someone guide me the way please thank you!
The errors occur at the last 2 closing }
1 error:
Syntax error on token "}", { expected after this
token
2 error:
Syntax error, insert "}" to complete
ClassBody
Here is my code
public class BinaryTree {
// root node pointer. Will be null for an empty tree
private Node root;
/*
-- Node --
The binary tree is built using this nested node class.
Each node stores on data element, and has left and right
sub-tree pointer which may be null.
The node is a "dumb" nested class -- we just use it for storage;
*/
private static class Node { // Node class
Node left;
Node right;
int data;
Node(int newData) { // create Node
left = null;
right = null;
data = newData;
}
}
/*
Creates an empty binary tree == null root pointer
*/
public void BinaryTree() {
root = null;
}
/*
Returns true if the given target is in the binary tree
*/
public boolean lookup(int data) { // look up a number
return(lookup(root, data)); // use this to parse through a tree to search for element
}
/*
recursive lookup -- given a node, recur
down searching for the given data.
*/
private boolean lookup(Node node, int data) {
if (node == null) {
return(false);
}
if (data == node.data) {
return(true);
}
else if (data < node.data) {
return(lookup(node.left, data));
}
else {
return(lookup(node.right, data));
}
}
public void insert(int data) {
root = insert(root, data);
}
/*
Recursive insert -- given a 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);
}
}
} // I get an error here #1
return (node);
} // I also get an error here #2
Change insert to :
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 eclipse : Press Ctrl + a and then Ctrl+shift+f to format code.. you will get to know such errors easily...
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);// I get an error here #1
---> }
You wrote return statement outside. I moved it inside. Please update.
Error is because you have the following statement
return (node);
out of your insert method
complete working code
public class BinaryTree {
// root node pointer. Will be null for an empty tree
private Node root;
/*
-- Node --
The binary tree is built using this nested node class.
Each node stores on data element, and has left and right
sub-tree pointer which may be null.
The node is a "dumb" nested class -- we just use it for storage;
*/
private static class Node { // Node class
Node left;
Node right;
int data;
Node(int newData) { // create Node
left = null;
right = null;
data = newData;
}
}
/*
Creates an empty binary tree == null root pointer
*/
public void BinaryTree() {
root = null;
}
/*
Returns true if the given target is in the binary tree
*/
public boolean lookup(int data) { // look up a number
return(lookup(root, data)); // use this to parse through a tree to search for element
}
/*
recursive lookup -- given a node, recur
down searching for the given data.
*/
private boolean lookup(Node node, int data) {
if (node == null) {
return(false);
}
if (data == node.data) {
return(true);
}
else if (data < node.data) {
return(lookup(node.left, data));
}
else {
return(lookup(node.right, data));
}
}
public void insert(int data) {
root = insert(root, data);
}
/*
Recursive insert -- given a 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);
}
}
// I get an error here #1
return (node);
} } //
You're returning at the end of the class outside of any method, which is an error.
I've been trying to create a integer binary search tree with Java and for some reason, I've been going wrong with adding new nodes to the tree.
Here is the NODE class.
class NODE
{
NODE left = null, right = null;
int info;
public NODE(int x)
{
info = x;
}
}
and here's the BST(Binary Seatch Tree) class with the insert() method.
class BST
{
NODE tree = null;
public void insert(int x)
{
NODE node = new NODE(x);
NODE temp = tree;
while(true)
{
if(temp == null)
{
temp = node;
break;
}
else if(temp.info > x) temp = temp.left;
else temp = temp.right;
}
}
//other methods present here
}
For reasons that I could not figure out, the insert() method is going wrong.
The object tree carries null in it even after the insert() method is called.
Can you find something spotty in the code?
Thanks!
Use a recursive insert method in the NODE class (instead of utilizing an infinite loop as you did):
public void insert(int x) {
if(x < this.info) {
if(this.left == null)
this.left = new NODE(x);
else
this.left.insert(x);
}
else {
if(this.right == null)
this.right = new NODE(x);
else
this.right.insert(x);
}
}
And your BST class would have the following insert method (simply calls the other insert method):
public void insert(int x) {
if(tree == null)
tree = new NODE(x);
else
tree.insert(x);
}
The main insert method is in the NODE class because it must recursively call itself on nodes within the tree.
Of course tree remains null - you don't assign anything to this field.
After temp = tree; and temp = node; only temp is changed, not tree.
The insert() method should insert the child of a node into the tree, calling an already declared Node as a parameter. e.g.:
//Returns true/false depending on whether the insert is successful
public boolean insert(int x, Node node, boolean leftChild) {
if (node == null) return false;
Node child = new Node(x);
if (leftChild) {
if (node.left != null) return false;
node.left = child;
} else {
if (node.right != null) return false;
node.right = child;
}
return true;
}
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.