Problem in binary tree; need help - java

can you help me please? I am making a binary tree with node insertion. How can I insert the new node to the current node in respect of BST rule?
Example: first the root is empty.
Input number: 50
This will display "Success!"
Insert number: 40
Successfully inserted in the left subtree of 50
insert number: 20
successfully inserted in the left subtree of 40
insert number: 80
successfully inserted in the right subtree of 50
Can you help me please? Thank you in advance hoping for your positive response...
Here's my code:
class Node
{
public int num;
public Node llink;
public Node rlink;
}
public class BinaryTreeOperations
{
//public Node llink=null;
// public Node rlink=null;
private Node temp;
private Node current;
private Node root;
public boolean isEmpty()
{
return root==null;
}
public void insertNum(int n)
{
temp=null;
current=null;
Node newNode = new Node();
newNode.num=n;
newNode.llink=null;
newNode.rlink=null;
if(isEmpty())
{
root=newNode;
System.out.println("Successfully inserted!");
}
else
{
temp=root;
while(temp!=null)
{
current = temp;
root = current;
temp=null;
}
if(n<current.num)
{
current.llink=newNode;
//current.llink=temp;
System.out.println("inserted on the left subtree " +current.num);
}
else
{
newNode.rlink=newNode;
System.out.println("inserted on the right subtree "+current.num );
}
}
}

Your while loop seems wrong. What you really want to do is start at the root and traverse the tree until you reach the node which will serve as the parent of your new node. Below you are not doing any traversal or inspection to find where the new node should go. That is what you really need to be doing.
while(temp!=null) {
current = temp;
root = current;
temp=null;
}
Should be something like this:
while(parent not found) {
if (new node is smaller than current) {
if (current has left child) {
assign left child to current and loop
} else {
make current the parent of the new node
}
} else {
....
}
}

else
{
temp=root;
while(temp!=null)
{
current = temp;
root = current;
temp=null;
}
This loop will only ever run once. Probably not what you intended. :)
if(n<current.num)
{
current.llink=newNode;
//current.llink=temp;
System.out.println("inserted on the left subtree " +current.num);
}
else
{
newNode.rlink=newNode;
System.out.println("inserted on the right subtree "+current.num );
}
In one branch you are assigning to current.llink, in the other branch you are assigning to newNode.rlink. Oops. :)

Your methodology for adding to the binary search tree seems incorrect.
You need to read up on Binary Search Trees to figure out how you will maintain the structure of your tree.
Below is some code that shows how to add to a Binary Search Tree, but I define a tree as empty if it contains no data.
public boolean isEmpty() {
return data == null;
}
The rest of the code is pretty self explanatory and should help you figure out how to add to the tree to maintain order.
public boolean add(Comparable target) {
if(isEmpty()) {
setData(target);
this.setLeftTree(new BinarySearchTree());
this.setRightTree(new BinarySearchTree());
return true;
} else {
int comparison = getData().compareTo(target);
if(comparison == 0)
return false;
else {
if(comparison < 0) {
return getRightTree().add(target);
} else {
return getLeftTree().add(target);
}
}
}
}
Let me know if you have any other questions.

Related

Recursion while adding nodes in tree data structure

I'm new to understanding and learning data structures.I have tried to implement Tree data structure after searching some tutorials.It seems well but i don't understand the recursive behavior which was a bit strange here.Can someone help me in understanding the code.
I have included some print statements to understand the recursive flow but was not able to understand why the current refernce is not being returned?
public class TreeCheck {
Node root;
private Node addRecursive(Node current, int value) {
if (current == null) {
return new Node(value);
}
if (value < current.value) {
current.left = addRecursive(current.left, value);
} else if (value > current.value) {
current.right = addRecursive(current.right, value);
} else {
// value already exists
return current;
}
System.out.println("current is "+current.value); //Please compare in the
image why the
return current;
}
public void add(int value) {
root = addRecursive(root, value);
System.out.println("value is "+root.value);
}
public static void main(String h[]){
TreeCheck bt = new TreeCheck();
bt.add(6);
bt.add(4);
bt.add(8);
bt.add(3);
bt.add(5);
bt.add(7);
bt.add(9);
}
class Node {
int value;
Node left;
Node right;
Node(int value) {
this.value = value;
right = null;
left = null;
}
}
Why the current statement is being printed twice and always returns the root element only when the current is re-assigned sometimes?
It isn't printing it right for the following reasons:
First, your add method is always printing "value is " + root.value", which is confusing when trying to figure out how the program adds values.
Second, your add method prints after the value has been inserted, I would restructure it so that it prints the value to be inserted first, and then the path in which the nodes are being checked:
public void add(int value) {
// you always printed out the value of the root node with every call to this method
// I updated it to reflect the input argument
System.out.println("\nvalue is " + value);
root = addRecursive(root, value);
}
Now each block is its own insertion and the program flow is easier to trace.
Next: current is actually printing correctly, just in reverse order. Let us say you are inserting 5, the current nodes to be printed will be: the parent of 5, which is 4, then the parent of 4, which is 6.
This image might help to visualize the tree (sorry for my ugly hand writing)
If you want to change the order, do it like this (place the print of current before the if statement):
private Node addRecursive(Node current, int value) {
if (current == null) {
return new Node(value);
}
System.out.println("current is " + current.value);
if (value < current.value) {
current.left = addRecursive(current.left, value);
} else if (value > current.value) {
current.right = addRecursive(current.right, value);
} else {
// value already exists
return current;
}
return current;
}
Furthermore, if you would like to see if your insertion into a binary search tree works, you can use this method to print your tree in ascending order:
public void inOrderPrint(Node node){
if (node.left != null) {
inOrderPrint(node.left);
}
System.out.println(node.value);
if (node.right != null) {
inOrderPrint(node.right);
}
}
And call it like this in your main:
public static void main(String h[]) {
TreeCheck bt = new TreeCheck();
bt.add(6);
bt.add(4);
bt.add(8);
bt.add(3);
bt.add(5);
bt.add(7);
bt.add(9);
System.out.println("-------");
bt.inOrderPrint(bt.root);
}
I hope that was helpful and that I explained it clearly. Please comment if I made an incorrect statement and I will edit the post accordingly.
https://www.geeksforgeeks.org/binary-search-tree-set-1-search-and-insertion/
Go through the above article it should help.
Happy Learning !!

What changes when implementing lazy deletion into a binary search tree exactly?

Okay so I've been looking into this for days and everytime I think I've gotten it down I start writing code and I get to a point where I just can't figure out what exactly to do.
The tree isn't recursive, so I can follow everything really until I start trying to modify it so it uses lazy deletion instead of real deletion. (Right now it nulls out the node it deletes)
What I have managed to figure out:
I added a flag to the node class to set them as deleted
I've implemented a search method that works, it even seems to register if my nodes are deleted or not(lazily)
I know that the rest of the tree class should treat the nodes that are flagged as deleted such that they are not there.
What I don't know:
I've looked at MANY resources and some say all you need to do is set
the node's deleted flag to true. Does this mean that I don't have to
worry about the linking after their flag is set?
Is an appropriate way to do this very superficial? As in, just don't let the methods report that something is found if the flag is set to deleted even though the methods do find something?
In what method(s) should I change to use lazy deletion? Only the delete() method?
If I only change the delete method, how is this picked up by the other methods?
Does the search method look okay?
Here's the rest of the code so you can see what I'm using. I'm really frustrated because I honestly understand how to delete nodes completely way better then this stupid lazy deletion implementation. It's what they teach in the book! lol
Please help... :(
Search Method
So here's my search method:
public String search(E data){
Node<E> current = root;
String result = "";
while(current != null){
if(data.compareTo(current.e) < 0){
current = current.left;
}
else if (data.compareTo(current.e) > 0){
current = current.right;
}
else{
if (current.isDeleted == false){
return result += "Found node with matching data that is not deleted!";
}
else{
return result += "Found deleted data, not usable, continuing search\n";
}
}
}
return result += "Did not find non-deleted matching node!";
}
Tree Class
Tree Code (The real deletion method is commented out at the end so I could replace it with the lazy deletion):
package mybinarytreeexample;
public class MyBinaryTree> {
private Node<E> root = null;
public class Node<E> {
public boolean isDeleted = false;
public E e = null;
public Node<E> left = null;
public Node<E> right = null;
}
public boolean insert(E e) {
// if empty tree, insert a new node as the root node
// and assign the elementy to it
if (root == null) {
root = new Node();
root.e = e;
return true;
}
// otherwise, binary search until a null child pointer
// is found
Node<E> parent = null;
Node<E> child = root;
while (child != null) {
if (e.compareTo(child.e) < 0) {
parent = child;
child = child.left;
} else if (e.compareTo(child.e) > 0) {
parent = child;
child = child.right;
} else {
if(child.isDeleted){
child.isDeleted = false;
return true;
}
return false;
}
}
// if e < parent.e create a new node, link it to
// the binary tree and assign the element to it
if (e.compareTo(parent.e) < 0) {
parent.left = new Node();
parent.left.e = e;
} else {
parent.right = new Node();
parent.right.e = e;
}
return true;
}
public void inorder() {
System.out.print("inorder: ");
inorder(root);
System.out.println();
}
private void inorder(Node<E> current) {
if (current != null) {
inorder(current.left);
System.out.printf("%3s", current.e);
inorder(current.right);
}
}
public void preorder() {
System.out.print("preorder: ");
preorder(root);
System.out.println();
}
private void preorder(Node<E> current) {
if (current != null) {
System.out.printf("%3s", current.e);
preorder(current.left);
preorder(current.right);
}
}
public void postorder() {
System.out.print("postorder: ");
postorder(root);
System.out.println();
}
private void postorder(Node<E> current) {
if (current != null) {
postorder(current.left);
postorder(current.right);
System.out.printf("%3s", current.e);
}
}
public String search(E data){
Node<E> current = root;
String result = "";
while(current != null){
if(data.compareTo(current.e) < 0){
current = current.left;
}
else if (data.compareTo(current.e) > 0){
current = current.right;
}
else{
if (current.isDeleted == false){
return result += "Found node with matching data that is not deleted!";
}
else{
return result += "Found deleted data, not usable, continuing search\n";
}
}
}
return result += "Did not find non-deleted matching node!";
}
public boolean delete(E e) {
}
// an iterator allows elements to be modified, but can mess with
// the order if element not written with immutable key; it is better
// to use delete to remove and delete/insert to remove or replace a
// node
public java.util.Iterator<E> iterator() {
return new PreorderIterator();
}
private class PreorderIterator implements java.util.Iterator<E> {
private java.util.LinkedList<E> ll = new java.util.LinkedList();
private java.util.Iterator<E> pit= null;
// create a LinkedList object that uses a linked list of nodes that
// contain references to the elements of the nodes of the binary tree
// in preorder
public PreorderIterator() {
buildListInPreorder(root);
pit = ll.iterator();
}
private void buildListInPreorder(Node<E> current) {
if (current != null) {
ll.add(current.e);
buildListInPreorder(current.left);
buildListInPreorder(current.right);
}
}
// check to see if their is another node in the LinkedList
#Override
public boolean hasNext() {
return pit.hasNext();
}
// reference the next node in the LinkedList and return a
// reference to the element in the node of the binary tree
#Override
public E next() {
return pit.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException("NO!");
}
}
}
// binary search until found or not in list
// boolean found = false;
// Node<E> parent = null;
// Node<E> child = root;
//
// while (child != null) {
// if (e.compareTo(child.e) < 0) {
// parent = child;
// child = child.left;
// } else if (e.compareTo(child.e) > 0) {
// parent = child;
// child = child.right;
// } else {
// found = true;
// break;
// }
// }
//
//
// if (found) {
// // if root only is the only node, set root to null
// if (child == root && root.left == null && root.right == null)
// root = null;
// // if leaf, remove
// else if (child.left == null && child.right == null) {
// if (parent.left == child)
// parent.left = null;
// else
// parent.right = null;
// } else
// // if the found node is not a leaf
// // and the found node only has a right child,
// // connect the parent of the found node (the one
// // to be deleted) to the right child of the
// // found node
// if (child.left == null) {
// if (parent.left == child)
// parent.left = child.right;
// else
// parent.right = child.right;
// } else {
// // if the found node has a left child,
// // the node in the left subtree with the largest element
// // (i. e. the right most node in the left subtree)
// // takes the place of the node to be deleted
// Node<E> parentLargest = child;
// Node<E> largest = child.left;
// while (largest.right != null) {
// parentLargest = largest;
// largest = largest.right;
// }
//
// // replace the lement in the found node with the element in
// // the right most node of the left subtree
// child.e = largest.e;
//
// // if the parent of the node of the largest element in the
// // left subtree is the found node, set the left pointer of the
// // found node to point to left child of its left child
// if (parentLargest == child)
// child.left = largest.left;
// else
// // otherwise, set the right child pointer of the parent of
// // largest element in the left subtreeto point to the left
// // subtree of the node of the largest element in the left
// // subtree
// parentLargest.right = largest.left;
// }
//
// } // end if found
//
// return found;
What changes is that your tree only grows in term of real space used, and never shrinks. This can be very useful if you choose a list as a data-structure to implement your tree, rather than the usual construct Node E {V value; E right; E; left}. I will come back on this later.
I've looked at MANY resources and some say all you need to do is set
the node's deleted flag to true. Does this mean that I don't have to
worry about the linking after their flag is set?
Yes, if by linking you mean node.left, node.right. Delete simply mark as deleted and that's it. It change nothing else, and it should not, because x.CompareTo(y) must be still working even if x or y are marked as deleted
Is an appropriate way to do this very superficial? As in, just don't
let the methods report that something is found if the flag is set to
deleted even though the methods do find something?
Well by definition of this method "something" means a node without the deleted flag. Anything with the deleted flag is "nothing" for the user of the tree.
what method(s) should I change to use lazy deletion? Only the delete()
method?
Of course not. You already changed the search method yourself. Let's take the isEmpty(). You should keep a counter of deleted nodes and one of total nodes. If they are equal the tree is empty. Otherwise the tree is not.
There is a small bug in your algorithm. When you insert and find out that you land on a deleted node, you just unmark that node. You must also set the value of the node. After all compareTo doesnt insure all fields are strictly equal, just that the objects are equivalent.
if(child.isDeleted){
child.isDeleted = false;
child.e = e; <---- missing
return true;
}
There might be others.
Side Note:
As said before one instance where this method is useful is a tree backed by an list (let's say array list). With this method the children of element at position i are at position 2*i+1 and 2*i+2. Usually when you delete a node p with children, you replace that node with the leftmost node q of the right subtree (or rightmost node in the left subtree). Here you can just mark p as deleted and swap the value of the deleted node and leftmost. Your array stays intact in memory

Inserting Elements in Binary Tree in Java

I have written a code to insert an element in a binary tree in java. Here are the functions to do the same:
public void insert(int data)
{
root = insert(root, data);
}
private Node insert(Node node, int data)
{
if (node == null)
node = new Node(data);
else
{
if (node.getRight() == null)
node.right = insert(node.right, data);
else
node.left = insert(node.left, data);
}
return node;
}
However when I traverse the tree, the answer I get is wrong. Here are the traversal functions (preorder):
public void preorder()
{
preorder(root);
}
private void preorder(Node r)
{
if (r != null)
{
System.out.print(r.getData() +" ");
preorder(r.getLeft());
preorder(r.getRight());
}
}
Okay so as suggested here's the definition for the Node class:
public class Node {
public int data;
public Node left, right;
/* Constructor */
public Node() {
left = null;
right = null;
data = 0;
}
/* Constructor */
public Node(int d, Node l, Node r) {
data = d;
left = l;
right = r;
}
//Constructor
public Node(int d) {
data = d;
}
/* Function to set link to next Node */
public void setLeft(Node l) {
left = l;
}
/* Function to set link to previous Node */
public void setRight(Node r) {
right = r;
}
/* Function to set data to current Node */
public void setData(int d) {
data = d;
}
/* Function to get link to next node */
public Node getLeft() {
return left;
}
/* Function to get link to previous node */
public Node getRight() {
return right;
}
/* Function to get data from current Node */
public int getData() {
return data;
}
}
I have re-checked the algorithm for traversal many times, and it's working perfectly. I believe the problem is in the insertion algorithm. Any suggestions?
If I understood correctly, you want to fill your binary tree in "layers". E.g. you want to put something into depth 4 only if depth 3 is "full binary tree".
Then the problem is whole logic of your insert algorithm that is DFS-based. In other words it inserts elements deeper and deeper on the one side instead of building full binary tree on both sides.
If you look closer to your insert algorithm you will see that once you skip "right" subtree, you will never return to it - even if the "left" subtree is already full binary tree. That leads to the tree that will be growing deeper and deeper on the left side but not growing on the right side.
Speaking in programming language. You do:
(node.right != null) && (node.left != null) => insert (node.left)
but you can't do this (start inserting node.left). What if node.left has both children and node.right has no children? You will attempt to insert to the left even you should do it in node.right.
So what you really need to do insertion BFS-based. That means you will traverse the tree for insertion "in layers". Queue should be your new friend here:-) (not the stack/recursion):
public void insert(int data) {
if (root == null) {
root = new Node(data);
return;
}
Queue<Node> nodesToProcess = new LinkedList<>();
nodesToProcess.add(root);
while (true) {
Node actualNode = nodesToProcess.poll();
// Left child has precedence over right one
if (actualNode.left == null) {
actualNode.left = new Node(data);
return;
}
if (actualNode.right == null) {
actualNode.right = new Node(data);
return;
}
// I have both children set, I will process them later if needed
nodesToProcess.add(actualNode.left);
nodesToProcess.add(actualNode.right);
}
}
Your method returns given node, but your method has to return inserted node which is node.right or node.left

Binary Tree implementation for adding nodes level by level

I have been trying to write a program for creating a binary tree .I wish add nodes level by level .When i google the topic all i get is binary search tree .
here is the code
public class BinaryTree
{
public static void main(String[] args)
throws NullPointerException
{
Tree myTree = new Tree();
myTree.add(2,new Node(4));
myTree.add(4,new Node(5));
myTree.add(2,new Node(6));
//myTree.add(2,new Node(7));
}
}
class Node
{
int data;
boolean visited;
Node left,right;
Node(int data)
{
left=null;
right=null;
visited=false;
this.data=data;
}
}
class Tree
{
Node root;
int level,cLevel;
Tree()
{
root=null;
level=0;
cLevel=level-1;
}
protected void add(int data,Node node)
{
System.out.println("node.data k: "+node.data);
Node t;
if(root==null)
{
Node n=new Node(data);
root=n;
root.visited=true;
System.out.println("root visited"+root.data+""+root.visited);
level++;
cLevel++;
return;
}
while(root!=null)
{
}
}
}
I want to add new nodes level by level ,new level should not be created until a level isnt comleted ,all i get by googling is binary search tree .what should i do ,i have tried to use
depth first and breath first approach which didnt prrove helpfull .
You could achieve this by maintaining a queue of nodes which do not yet have two children. Every time you add a new node, stick it on the end of this queue, and also make it a child of the node at the front of this queue. Once the node at the front has two children, remove it from the queue. This way you'll build it up one level at a time, left to right, and only move on to the next level once the current one is finished.
You could also try "Limited Depth-first search"
A recursive implementation in Java using part of your code could be:
class Tree
{
Node root;
int level,cLevel;
Tree()
{
root=null;
level=0;
cLevel=level-1;
}
protected void add(int data)
{
System.out.println("data k: "+ data);
Node t;
if(root==null)
{
root=new Node(data);
level++;
} else {
cLevel = 0;
boolean added = add(data, root);
//Couldn't add to current level, add new level
if (!added){
level++;
cLevel = 0;
add(data, root);
}
}
}
private boolean add(int data, Node node)
{
cLevel++;
boolean added;
//Depth limited
if (cLevel<=level){
added = true;
//Try to add to current node
if (node.left == null)
node.left = new Node(data);
else if (node.right == null)
node.right = new Node(data);
else if (!add(data, node.left)) //Recursively trying to add to children
added = add(data, node.right);
} else {
added=false;
}
cLevel--;
return added;
}
}
Hope it helps.
Done with it.Thanks Animatinator .Although i have tested it with hardcode as i do not have time right now ,i have a paper early morning of Compiler Construction .
protected void add(int data,Tree mytree)
{
if(root==null)
{
root=new Node(data);
myList.addLast(root);
root.count++;
return;
}
Node node=mytree.myList.getFirst();
if(root!=null)
{
if(node.left==null)
{
node.count++;
node.left=new Node(data);
mytree.myList.add(node.left);
return;
}
else
{
node.count++;
node.right=new Node(data);
mytree.myList.add(node.right);
}
if(node.left!=null & node.right!=null)
{
mytree.myList.removeFirst();
}
}
}

Write a method to find the common elements between two BSTs, and insert them in 3rd BST

I got an insert method and a search method, and I was thinking of a way to loop through the binary search tree and use a method like get nodes then search for it on the other binary search tree and if it comes true then I insert it that element, but the problem is I can't come up with a way to get the nodes based on index because its different than linkedList for example and can't think of a way to get the nodes to begin with; to sum up, I actually don't the proper way to start to solve that question.
public class BinarySearchTree extends BinaryTree {
//default constructor
//Postcondition: root = null;
public BinarySearchTree() {
super();
}
//copy constructor
public BinarySearchTree(BinarySearchTree otherTree) {
super(otherTree);
}
public class BinaryTree {
//Definition of the node
protected class BinaryTreeNode {
DataElement info;
BinaryTreeNode llink;
public DataElement getInfo() {
return info;
}
public BinaryTreeNode getLlink() {
return llink;
}
public BinaryTreeNode getRlink() {
return rlink;
}
BinaryTreeNode rlink;
}
protected BinaryTreeNode root;
//default constructor
//Postcondition: root = null;
public BinaryTree() {
root = null;
}
//copy constructor
public BinaryTree(BinaryTree otherTree) {
if (otherTree.root == null) //otherTree is empty
{
root = null;
} else {
root = copy(otherTree.root);
}
}
public BinaryTreeNode getRoot() {
return root;
}
public boolean search(DataElement searchItem) {
BinaryTreeNode current;
boolean found = false;
current = root;
while (current != null && !found) {
if (current.info.equals(searchItem)) {
found = true;
} else if (current.info.compareTo(searchItem) > 0) {
current = current.llink;
} else {
current = current.rlink;
}
}
return found;
}
public int countEven() {
return countEven(root);
}
public void insert(DataElement insertItem) {
BinaryTreeNode current;
BinaryTreeNode trailCurrent = null;
BinaryTreeNode newNode;
newNode = new BinaryTreeNode();
newNode.info = insertItem.getCopy();
newNode.llink = null;
newNode.rlink = null;
if (root == null) {
root = newNode;
} else {
current = root;
while (current != null) {
trailCurrent = current;
if (current.info.equals(insertItem)) {
System.out.println("The insert item is already in" + "the list -- duplicates are" + "not allowed.");
return;
} else if (current.info.compareTo(insertItem) > 0) {
current = current.llink;
} else {
current = current.rlink;
}
}
if (trailCurrent.info.compareTo(insertItem) > 0) {
trailCurrent.llink = newNode;
} else {
trailCurrent.rlink = newNode;
}
}
}
Traverse down to the left end of one tree, compare it with the root node of the other tree. If found equal, insert it into your third tree. If unequal, then check if it's less than or greater than the root of second tree. If less than, then traverse to the left child of the second tree and call your search method again, else, traverse to the right child of the second tree and call your search method again. Then repeat the whole process with the right node of the opposing starting node of first tree that you chose and call the search method again. Keep moving up the first tree as you repeat the process.
Here's a sample code(keeping in mind you have not provided any details about your trees whatsoever):
void search(Node node1, Node root2){
if(root2 == null)
return;
if(node1.data == root2.data){
//copy to your third tree
return;
}
else{
if(node1.data < root2.data){
root2 = root2.left;
search(node1, root2);
}
else{
root2 = root2.right;
search(node1, root2);
}
}
}
void common(Node root1, Node root2){
if(root1 != null){
common(root1.left, root2);
search(root1, root2);
common(root1.right, root2);
}
}
I'm assuming you need to modify the BinarySearchTree class, so the following is written with that assumption.
You can traverse the tree by first calling getRoot() which will return the root of the tree (a BinaryTreeNode) then access the nodes' left and right children by calling getLLink() and getRLink(), respectively. From each node you can get its value via getInfo that you can search for in the other tree (by calling the search() method on the second tree).
Note: as it is, you can only call methods on the nodes from within methods of BinarySearchTree as access to BinaryTreeNode is restricted to BinaryTree and classes deriving from it (for which BinarySearchTree qualifies)

Categories