Please explain the given binary tree code that is in java - java

I could not find people to explain me this java code properly so finally I am posting this question.please explain the process how that particular statement is affecting the tree.the problems are stated in the comments.I have problems in the BST class.
import java.util.Scanner;
class BSTNode
{
BSTNode left, right;
int data;
public BSTNode()
{
left = null;
right = null;
data = 0;
}
public BSTNode(int n)
{
left = null;
right = null;
data = n;
}
public void setLeft(BSTNode n)
{
left = n;
}
public void setRight(BSTNode n)
{
right = n;
}
public BSTNode getLeft()
{
return left;
}
public BSTNode getRight()
{
return right;
}
public void setData(int d)
{
data = d;
}
public int getData()
{
return data;
}
}
class BST
{
private BSTNode root;
public BST()
{
root = null;
}
public boolean isEmpty()
{
return root == null;
}
Why is the insert function written like root=insert(...... Is it returning root = actual root element each time?
public void insert(int data)
{
root = insert(root, data);
}
I understand how the inserting process is going on but what is the insert function returning? I know that it returns some node but how the is the process going on during iteration?
private BSTNode insert(BSTNode node, int data)
{
if (node == null)
node = new BSTNode(data);
else
{
if (data <= node.getData())
node.left = insert(node.left, data);
else
node.right = insert(node.right, data);
}
return node;
}
public void delete(int k)
{
if (isEmpty())
System.out.println("Tree Empty");
else if (search(k) == false)
System.out.println("Sorry "+ k +" is not present");
else
{
root = delete(root, k);
Again, why is the delete function written like root=delete(.....? Is it returning root =actual root element each time?
System.out.println(k+ " deleted from the tree");
}
}
private BSTNode delete(BSTNode root, int k)
{
BSTNode p, p2, n;
if (root.getData() == k)
{
BSTNode lt, rt;
lt = root.getLeft();
rt = root.getRight();
if (lt == null && rt == null)
return null;
else if (lt == null)
{
p = rt;
return p;
}
else if (rt == null)
{
p = lt;
return p;
}
else
{
//case when we delete node having both children.
p2 = rt;
p = rt;
//getting the min of the right child subtree in p variable .
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
Please explain what is happening here and why is p2 i.e rt being returned.
return p2;
}
}
if (k < root.getData())
{
n = delete(root.getLeft(), k);
root.setLeft(n);
}
else
{
n = delete(root.getRight(), k);
root.setRight(n);
}
return root;
}
public int countNodes()
{
return countNodes(root);
}

In the delete portion of your code, what you are doing is checking to see if the node (called root) has its data value equal to the value you want to delete (k). If that is true, then you examine both children which you seem to grasp. So then we get down to your question when you have both children of the node not null. In this case you want to delete the current node (root) of the subtree you are on, but you need to choose a node (either the left or right) to promote to the position of this node. So (assuming this tree is not balanced) you simply make a choice (left or right) of the subtree to promote to the know root. Keep in mind here that you are only calling the current node root because it is the root of some subtree within the larger tree (this does not mean the actual root of the tree unless that is the value that was passed in as root). Knowing that all of the values in the right child subtree are going to be greater than those in the left child subtree, you simply take the current node's left subtree then recurse as far down the left children of the right subtree as you can go until you're to the end. You then set this node's left child to the entire left subtree.
//case when we delete node having both children.
p2 = rt;
p = rt;
//getting the min of the right child subtree in p variable .
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
Notice in the statement
p = rt;
You are setting P to be the root of the of the right subtree. Then p is now the right child of the current root passed in.
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
This is basically saying that for that right subtree, If the root node has a left child then set p to that and keep doing so until that value is null. This will keep going down the left children of that right subtree. Finally once that value is null
p.setLeft(lt);
Will set the left child of that left most leaf in the right subtree to the entire left subtree that you started with. And return the node that you said was the right subtree of the original (now with the left subtree of the original appended to its leftmost leaf).

Related

How to find a Node of a Binary Search Tree without using a recursive method

If I have a Method that only takes value as an argument (not Node) called public Node finder (E val) how can I find the respective Node regardless of the height and width of the tree. If the method took Node as an argument then it would be an easy solution to use recursion. But unfortunately I am not allowed to change the method signature. How can I do this the smart way rather than the dumb way I am trying below which would just end up with a ton of embedded if functions
public class BinarySearchTree<E extends Comparable<E>> {
class Node {
E value;
Node leftChild = null;
Node rightChild = null;
Node(E value) {
this.value = value;
}
}
public Node finder(E val) {
if (val == null) return null;
if (root == null) return null;
boolean flag = false;
Node temp = root;
//find if Root Node matches value
if(temp.value.compareTo(val) == 0) {
flag = true;
return temp;
}
//if value is less than root check the left branch
else if (temp.value.compareTo(val) > 0) {
if(temp.leftChild.value.compareTo(val) == 0) {
flag = true;
return temp.leftChild;
}
//more if statements here
}
//if value is more than root check the right branch
else {
if(temp.rightChild.value.compareTo(val) == 0) {
flag = true;
return temp.rightChild;
}
//more if statements here
}
return null;
}
}
Binary search trees have this interesting property:
The left subtree of a node contains only nodes with values lesser than the node’s value.
The right subtree of a node contains only nodes with value greater than the node’s key.
Assuming your class BinarySearchTree holds a reference to the root, you can traverse the binary tree iteratively till you either reach the value or reach a leaf node which means your value does not exist in your binary search tree. The time complexity of this search operation is O(log(n)).
Here's some pseudocode
Find-Node(val):
node = root
while node != null:
if val == node.val then return root
if val < node.val then node = node.left
if val > node.val then node = node.right
return null

How to delete a node that has been found

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.

Binary Search Tree: Remove TreeNode with given value x non recursively using Java

I am trying to write a non-recursive method that removes a node within a binary search tree if it contains the given input value int x in Java. I figured I need to use a stack but can't seem to figure out how to remove the node without calling the function on itself.
This is my TreeNode class as of now.
class TreeNode {
private int data; // data item (key)
private TreeNode left; // this node's left child
private TreeNode right; // this node's right child
// The "external node" is a special node that acts as a sentinel.
private final static TreeNode externalnode = TreeNode.createExternalNode();
/* Return a TreeNode that represents an "external node"*/
public static TreeNode getExternalNode() {
return externalnode;
}
/* Creates a new TreeNode with no children.
*/
public TreeNode(int id) { // constructor
data = id;
left = externalnode;
right = externalnode;
}
I have tried this but cant get it to work.
public TreeNode removeB(int x){
if (this == externalnode) return externalnode;
TreeNode one = new TreeNode(this.data);
System.out.println(this);
Stack<TreeNode> s = new Stack();
s.push(one);
//System.out.println(s);
boolean check;
boolean check1;
while(check = true){
if(x == one.left.data){
System.out.println(one.left.data);
check = false;
return one.left;
}
if(x == one.right.data){
System.out.println(one.right.data);
check1 = false;
return one.right;
}
}
Your code needs to first perform a binary search to find the node to remove. In pseudo-code, it looks something like:
while (currentNode != null && currentNode.value != target) {
if (currentNode.value > target) {
currentNode = currentNode.left;
} else if (currentNode.value < target) {
currentNode = currentNode.right;
}
}
Once you've targeted that node, you replace it with one of its children, and then graft in the other orphaned child under it, just as you would add any node.

Binary tree : how can i implement LCA with one node?

Im trying to make it right now using recursion but Im having a hard time, I think I have a logical error.
please someone help me T_T
Here is my code so far
import java.util.ArrayList;
public class BTNode{
private BTNode root, left,right;
private int item;
public BTNode(int item){
this(item,null,null,null);
}
public BTNode(int item, BTNode left, BTNode right, BTNode root,int count){
this.item = item;
this.left = left;
this.right = right;
this.root = root;
this.count=count;
}
public void build(){
this.left = new BTNode(40);
this.left.root = this;
this.right = new BTNode(100);
this.right.root = this;
this.left.right = new BTNode(45);
this.left.right.root = this.left;
this.left.left = new BTNode(25);
this.left.left.root = this.left;
this.right.left = new BTNode(70);
this.right.left.root = this.right;
this.right.right = new BTNode(200);
this.right.right.root = this.right;
}
public void inorder(){//recursion
//traverse the left
if(left != null)
left.inorder();
//visit the root do the item
System.out.print(this.item+" ");
//traverse the right
if(right != null)
right.inorder();
}
public String inToString(){
return ((left == null)?"": left.inToString()) + item + " " + ((right == null)?"": right.inToString()+" ");
}
//preorder()
public void preorder(){
//visit the root do the item
System.out.print(this.item+" ");
//traverse the left
if(left != null)
left.preorder();
//traverse the right
if(right != null)
right.preorder();
}
//preToString()
public String preToString(){
return item+ " "+((left == null)?"": left.preToString())+ ((right == null)?"": right.preToString()+" ");
}
//postorder()
public void postorder(){
//traverse the left
if(left != null)
left.postorder();
//traverse the right
if(right != null)
right.postorder();
//visit root do the item
System.out.print(this.item+" ");
}
//postToString()
public String postToString(){
return ((left == null)?"": left.postToString()) + ((right == null)?"": right.postToString()+" ")+item+ " ";
}
//findsum-recursive
public int findsum(){
//traverse left,if null traverse to right then add the two item lastly add to the root
return ((left == null)?0: left.findsum()) + ((right == null)?0: right.findsum())+item;
}
//findlevel-recursive
public int findlevel(){
//check left && right if it is not null then iterate method recursively
if (left == null)
return 0;
else if(right == null)
return 0;
else
return 1 + left.findlevel();
}
/*
//ancestor-recursive
public BTNode ancestor(int value){
if(left.count== 2){//check the root
return left.ancestor();//traverse left node
}
System.out.print(item+" ");//print item if the left turns false
if(root != null){
right.ancestor();//traverse right node
}
}*/
public int count(){
//check if left || right are null then return 0, otherwise method were recursively executed
return (((left==null)?0:1+left.count())+((right==null)?0:1+right.count()));
}
public void reference(){
//check left != null print the root, traverse left, traverse right
if(left != null)
left.reference();
if(left != null)
System.out.print(item+" ");
if(right != null)
right.reference();
}
public void sort(){
}
public void insert(int given){
BTNode node = new BTNode(given);
if(item == 0)
root = node;
else
{
BTNode current = root; //points to the current Node
BTNode parent; //points to the parent Node
while(current != null)
{
if(item > given)
{
parent = current;
current = left;
}
if(item < given)
{
parent = current;
current = right;
}
}
current = node;
if(item < given)
right = node;
else
left = node;
}
right.inorder();
}
public boolean contains(int given){
return ((left==null)?false:left.contains(given))|| item==given || ((right == null)?false : right.contains(given));
/*if(left != null)
left.contains(given);
if(right != null)
right.contains(given);
return item == given;*/
}
public static void main(String[]args){
BTNode root = new BTNode(50);
root.build();
System.out.print("\nGiven :"+root.inToString());
System.out.println("\ninorder");
root.inorder();
System.out.println("\npreorder");
root.preorder();
System.out.println("\npostorder");
root.postorder();
System.out.println("\nfindsum");
System.out.println(root.findsum());
System.out.println("\nfindlevel");
//System.out.println(root.findlevel(200));
System.out.println(root.findlevel());
System.out.println("\nancestor");
//System.out.println(root.ancestor());
root.ancestor();
System.out.println("\ncount");
System.out.println(root.count());
System.out.println("\nreference");
//System.out.println(root.reference());
root.reference();
System.out.println("\nsort");
//System.out.print(root.sort());
root.sort();
System.out.println("\nContains");
System.out.println(root.contains(new Integer(70)));
System.out.println("\ninsert");
//System.out.print(root.sort());
root.insert(new Integer(71));
root.printinorder();
}
}
please also check my insertion mechanism... I dont think that is the right way to do it
Since your question is unclear, I am answering both of your potential questions.
1- If you want to find the minimum ancestor of a node, what you can do is given a node keep traversing up its parents while keeping a track of the smallest parent value found so far. Once you reach the root node you will have the smallest value. The time complexity of this algorithm is O(h) where h is the height of the tree. As this is very simple I am not giving a code sample here.
2- If you want to find the LCA (which is what you question title is about) you can do something very similar. If we assume that the keys n1 and n2 are present in Binary Tree, we can find LCA using single traversal of Binary Tree and without extra storage for path arrays. The idea is to traverse the tree starting from root. If any of the given keys (n1 and n2) matches with root, then root is LCA (assuming that both keys are present). If root doesn’t match with any of the keys, we recur for left and right subtree. The node which has one key present in its left subtree and the other key present in right subtree is the LCA. If both keys lie in left subtree, then left subtree has LCA also, otherwise LCA lies in right subtree. Here is an example code that you can tailor according to your need (this code works):
//Java implementation to find lowest common ancestor of
// n1 and n2 using one traversal of binary tree
/* Class containing left and right child of current
node and key value*/
class Node
{
int data;
Node left, right;
public Node(int item)
{
data = item;
left = right = null;
}
}
public class BinaryTree
{
//Root of the Binary Tree
Node root;
Node findLCA(int n1, int n2)
{
return findLCA(root, n1, n2);
}
// This function returns pointer to LCA of two given
// values n1 and n2. This function assumes that n1 and
// n2 are present in Binary Tree
Node findLCA(Node node, int n1, int n2)
{
// Base case
if (node == null)
return null;
// If either n1 or n2 matches with root's key, report
// the presence by returning root (Note that if a key is
// ancestor of other, then the ancestor key becomes LCA
if (node.data == n1 || node.data == n2)
return node;
// Look for keys in left and right subtrees
Node left_lca = findLCA(node.left, n1, n2);
Node right_lca = findLCA(node.right, n1, n2);
// If both of the above calls return Non-NULL, then one key
// is present in once subtree and other is present in other,
// So this node is the LCA
if (left_lca!=null && right_lca!=null)
return node;
// Otherwise check if left subtree or right subtree is LCA
return (left_lca != null) ? left_lca : right_lca;
}
/* Driver program to test above functions */
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(3);
tree.root.left.left = new Node(4);
tree.root.left.right = new Node(5);
tree.root.right.left = new Node(6);
tree.root.right.right = new Node(7);
System.out.println("LCA(4, 5) = " +
tree.findLCA(4, 5).data);
System.out.println("LCA(4, 6) = " +
tree.findLCA(4, 6).data);
System.out.println("LCA(3, 4) = " +
tree.findLCA(3, 4).data);
System.out.println("LCA(2, 4) = " +
tree.findLCA(2, 4).data);
}
}
This is method and code are from http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/ on this site you can run the code in IDE as well online.

Counting the nodes in a binary search tree

I need to create a recursive method that takes as a parameter the root node of a binary search tree. This recursive method will then return the int value of the total number of nodes in the entire binary search tree.
This is what I have so far:
public class BinarySearchTree<E> extends AbstractSet<E>
{
protected Entry<E> root;
//called by the main method
public int nodes()
{
return nodes(root);
}
//nodes() will count and return the nodes in the binary search tree
private int nodes(Entry<E> current)
{
if(current.element != null)
{
if(current.left == null && current.right == null)
{
if(current.element == root.element)
return 1;
deleteEntry(current);
return 1 + nodes(current.parent);
}
else if(current.left != null && current.right == null)
return nodes(current.left);
else if(current.left == null && current.right != null)
return nodes(current.right);
else if(current.left != null && current.right != null)
return nodes(current.left) + nodes(current.right);
} else return 1;
return 0;
}
The main method calls nodes like so:
System.out.println ("\nThis section finds the number of nodes "
+ "in the tree");
System.out.println ("The BST has " + bst.nodes() + " nodes");
So I was running the search by traveling in order, once I'd get to a node with no children I would delete the current node and return to the parent node and continue. I ran a debug of the method I have above and the program crashes with a NullPointerException() when it finally counts and removes all the nodes on the left and right side of the root node and tries to return 1.
This is for my lab, the method MUST be recursive.
I'm very lost at this point, does anyone know what I'm doing wrong?
You are making this way too complicated. The basic idea of object oriented programming is that you trust objects to do the jobs they know the answers to. So if I'm a parent, I can count myself, and I let my children count themselves, and so forth.
private int nodes(Entry<E> current) {
// if it's null, it doesn't exist, return 0
if (current == null) return 0;
// count myself + my left child + my right child
return 1 + nodes(current.left) + nodes(current.right);
}
You have several issues:
You're deleting nodes as you count them? Is nodes() supposed to clear the tree?
You're treating root==null, root!=null&left==null&&right==null, root!=null&left!=null&right==null, etc as separate cases. They're not. You have three cases, which are not entirely exclusive:
If the current node is not null, add one to the count. (This should always be the case. The only case where it might be false is if the current node == root, and we can detect and sidestep that beforehand.)
If the current node has a left child, add the left child's count.
If the current node has a right child, add the right child's count.
You're traversing back up the tree for some ungodly reason. Looks like it has something to do with deleting nodes...?
But the biggest thing in my opinion is, you're not giving enough autonomy to the Entrys. :P
A node can count its own children. Trust it to.
class Entry<E> {
...
int count() {
int result = 1;
if (left != null) result += left.count();
if (right != null) result += right.count();
return result;
}
}
public int nodes() {
return (root == null) ? 0 : root.count();
}
If your teacher is incompetent, and insists on some node-counting function outside a node, you can do the same thing you were trying to do:
private int nodes(Entry<E> current) {
int result = 1;
if (current.left) result += nodes(current.left);
if (current.right) result += nodes(current.right);
return result;
}
public int nodes() {
return (root == null) ? 0 : nodes(root);
}
But that teacher should be fired, in my opinion. The Entry class is the real tree; BinarySearchTree is really just a container for a reference to the root.
Also notice, i don't give a damn about the parents. If we start counting from the root, and each node counts its children, which count their children, etc etc... then all nodes will be accounted for.
public int countNodes(Node root){
// empty trees always have zero nodes
if( root == null ){
return 0;
}
// a node with no leafes has exactly one node
// note from editor: this pice of code is a micro optimization
// and not necessary for the function to work correctly!
if( root.left == null && root.right == null ){
return 1;
}
// all other nodes count the nodes from their left and right subtree
// as well as themselves
return countNodes( root.left ) + countNodes( root.right ) + 1;
}
After you delete current in: deleteEntry(current);, you use current.parent in return 1 + nodes(current.parent);
May be this's the reason of throwing NullPointerException..
Hey I have a very clean counting implemented for a binary tree:
public class Binary<T> where T: IComparable<T>
{
private Node _root;
public int Count => _root.Count;
public void Insert(T item)
{
Node newNode = new Node(item);
if (_root == null)
_root = newNode;
else
{
Node prevNode = _root;
Node treeNode = _root;
while (treeNode != null)
{
prevNode = treeNode;
treeNode = newNode.Item.CompareTo(treeNode.Item) < 1 ? treeNode.Left : treeNode.Right;
}
newNode.Parent = prevNode;
if (newNode.Item.CompareTo(prevNode.Item) < 1)
prevNode.Left = newNode;
else
prevNode.Right = newNode;
}
}
public class Node
{
public T Item;
public Node Parent;
public Node Left;
public Node Right;
public Node(T item, Node parent = null, Node left = null, Node right = null)
{
Item = item;
Parent = parent;
Left = left;
Right = right;
}
public int Count
{
get
{
int count = 1;
count += Left?.Count ?? 0;
count += Right?.Count ?? 0;
return count;
}
}
}
}
Maybe this helps you to understand how to implement a class for a simple binary tree with a count.
This implementation accesses the count through a count in the corresponding node in the tree.
Let me now if you are not familiar with the markup of .NET 4.6

Categories

Resources