Recursive function to calculate the height of a BST - java

The BST is as follows:
50 (Root 1)
/ \
40 80 (Root 2)
/ \
20 41
As you can see there are 2 root's that I am dealing with. I have tried the following code which does return the height of the tree from ROOT 1. I don't quite exactly know how to return the height from ROOT 2.
Any help on how to solve would be appreciated.
// Java program to find height of tree
// A binary tree node
class Node
{
int data;
Node left, right;
Node(int item)
{
data = item;
left = right = null;
}
}
class BinaryTree
{
Node root;
int maxDepth(Node node)
{
if (node == null)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node.left);
int rDepth = maxDepth(node.right);
/* use the larger one */
if (lDepth > rDepth)
return (lDepth + 1);
else
return (rDepth + 1);
}
}
/* 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);
System.out.println("Height of tree is : " +
tree.maxDepth(tree.root));
}

Your function for finding max depth seems like to work correctly. So fixing this issue is pretty simple.
System.out.println("Height of tree is : " +
tree.maxDepth(tree.root));
The above line prints out the height of the tree starting at the root. But if you were to start at "root 2" as you call it you would need to modify this line to start at the correct node.
System.out.println("Height of tree is : " +
tree.maxDepth(tree.root.right));

Adding an item to a Tree class should be made through a insert method.
And we can make the Node class private, it is used only by BinaryTree class.
A better data structure for a tree should be like the following, which has public insert and height methods.
public class BinaryTree {
private class Node {
private int value;
private Node left;
private Node right;
private Node(int value) {
this.value = value;
}
}
private Node root;
public void insert(int item) {
var node = new Node(item);
if (root == null) {
root = node;
return;
}
var current = root;
while (true) {
if (item < current.value) {
if (current.left == null) {
current.left = node;
break;
}
current = current.left;
} else {
if (current.right == null) {
current.right = node;
break;
}
current = current.right;
}
}
}
public int height() {
return height(root);
}
private int height(Node root) {
if (root == null)
return -1;
if (isLeaf(root))
return 0;
return 1 + Math.max(height(root.left), height(root.right));
}
private boolean isLeaf(Node node) {
return node.left == null && node.right == null;
}
}
And to use it, just add some values, and print the height.
It is way easier to insert an item with this tree class.
BinaryTree tree = new BinaryTree();
tree.insert(50);
tree.insert(40);
tree.insert(80);
tree.insert(20);
tree.insert(41);
System.out.println(tree.height());

Related

Why do we need a temporary node while inserting values in a node in Linked list?

I was creating a binary tree using linked list in java, which inserts the value according to the height of the tree i.e if the height is even or odd. I wrote a code which initially had no temporary node for insertion of values to the root node and further left or right subtree nodes. But when I displayed this tree, output had no root node as if it was overwritten.
Below is the code of my initial program. Concentrate on public void insert_node() function.
import java.util.Scanner;
public class binary_tree {
private TreeNode root;
private int height = 0;
public static class TreeNode {
private int data;
private TreeNode left;
private TreeNode right;
public TreeNode(int user_input) {
this.data = user_input;
}
}
public void insertNode(TreeNode newnode) { // HERE....I have used only root.
if (root == null) {
root = newnode;
height += 1;
return;
}
if (height % 2 != 0) {
System.out.println(height);
while (root.left != null) {
root = root.left;
}
root.left = newnode;
height += 1;
return;
}
while (root.right != null) {
root = root.right;
}
root.right = newnode;
height += 1;
}
public void display(TreeNode rootnode) {
TreeNode temp = rootnode;
if (temp == null)
System.out.println("Tree Empty !!!");
else {
System.out.println("press 1 for LEFT SUBTREE \npress 2 for RIGHT SUBTREE.");
Scanner sc = new Scanner(System.in);
int ch = sc.nextInt();
while (temp != null) {
System.out.println(temp.data + " $");
if (ch == 1)
temp = temp.left;
else
temp = temp.right;
}
}
System.out.println("Height of the tree = " + height);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
binary_tree bt = new binary_tree();
TreeNode newNode = new TreeNode(50);
bt.insertNode(newNode);
TreeNode newNode2 = new TreeNode(10);
bt.insertNode(newNode2);
TreeNode newNode3 = new TreeNode(100);
bt.insertNode(newNode3);
TreeNode newNode4 = new TreeNode(5);
bt.insertNode(newNode4);
TreeNode newNode5 = new TreeNode(1000);
bt.insertNode(newNode5);
bt.display(bt.root);
}
}
Output
press 1 for LEFT SUBTREE
press 2 for RIGHT SUBTREE.
3
10 $
1000 $
Height of the tree = 5
You can see in the above code, that the 50 $ is missing which was supposed to be the root node.
Now, if I use a temporary node which in my case is current_node then this root node sustains somehow. See in the code below.
import java.util.Scanner;
public class binary_tree {
private TreeNode root;
private int height = 0;
public static class TreeNode {
private int data;
private TreeNode left;
private TreeNode right;
public TreeNode(int user_input) {
this.data = user_input;
}
}
public void insertNode(TreeNode newnode) {
TreeNode current_node = root; //THIS IS THE TEMPORARY NODE
if (current_node == null) {
root = newnode;
height += 1;
return;
}
if (height % 2 != 0) {
System.out.println(height);
while (current_node.left != null) {
current_node = current_node.left;
}
current_node.left = newnode;
height += 1;
return;
}
while (current_node.right != null) {
current_node = current_node.right;
}
current_node.right = newnode;
height += 1;
}
public void display(TreeNode rootnode) {
TreeNode temp = rootnode;
if (temp == null)
System.out.println("Tree Empty !!!");
else {
System.out.println("press 1 for LEFT SUBTREE \npress 2 for RIGHT SUBTREE.");
Scanner sc = new Scanner(System.in);
int ch = sc.nextInt();
while (temp != null) {
System.out.println(temp.data + " $");
if (ch == 1)
temp = temp.left;
else
temp = temp.right;
}
}
System.out.println("Height of the tree = " + height);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
binary_tree bt = new binary_tree();
TreeNode newNode = new TreeNode(50);
bt.insertNode(newNode);
TreeNode newNode2 = new TreeNode(10);
bt.insertNode(newNode2);
TreeNode newNode3 = new TreeNode(100);
bt.insertNode(newNode3);
TreeNode newNode4 = new TreeNode(5);
bt.insertNode(newNode4);
TreeNode newNode5 = new TreeNode(1000);
bt.insertNode(newNode5);
bt.display(bt.root);
}
}
Output
press 1 for LEFT SUBTREE
press 2 for RIGHT SUBTREE.
3
50 $
100 $
1000 $
Height of the tree = 5
So anyone who can tell me what's happening here? What difference does that current_node is making?
Why do we need a temporary node while inserting values in a node in Linked list?
Because you are traversing to the leaves of the tree here:
while (current_node.left != null) {
current_node = current_node.left;
}
current_node.left = newnode;
height += 1;
In these lines of code, you are trying to find the leftmost leaf so as to insert newnode, right? You want to use a variable to keep track of which node you are currently on, and "go left" by doing someVariable = someVariable.left;.
You could use root to keep track of where you are at, but root already has a purpose - to record the root of the tree! If you did root = root.left;, you are making the left node of the original root be the new root! Say your tree was:
50
/ \
10 100
Doing root = root.left deletes most of it:
10
This is problematic because this means your tree essentially "forgets" about a part of the tree. Technically, The 50 and 100 nodes still exists and 50 is still connected to 10, but your binary_tree object doesn't have access to it anymore. The only point of access it has is root, which you have now set to the node 10.
What actually happens in your program is: it correctly inserts 50, 10, and 100, then when adding 5, tries to traverse down the left subtree. This makes the root "10", and adding 5 becomes:
10
/
5
It then adds 1000 correctly:
10
/ \
5 1000
Hence it prints 10 and 1000.
Using a brand new variable solves this problem, because the brand new variable has nothing to do with root.

Is depth between any two leaf node in binary tree greater than one

I've been working on this coding problem and have been able to successfully get the depth of each leaf node into a hash set. What I'm trying to do is determine if the difference in depth is of a leaf node is greater than one BEFORE that depth is added to the hash set. I don't want to put all of the leaf nodes in the hash set and use two for loops to check if there is a difference in depth greater than one. In my code below, the int variable count represents depth.
The problem is my code always returns true. Something is wrong with the code where is checks the difference in depths/count for each leaf node. Code is below. I'm trying to keep this method in O(n) time, and avoid O(n^2).
The depths of the four leaf nodes in this tree are : 3, 2, 2, 5
import java.util.*;
public class cakeEightWeekly {
static int count = 0;
public static class Node {
public int value;
public Node leftChild;
public Node rightChild;
public Node(int value) {
this.value = value;
}
public void setLeft(Node leftValue) {
this.leftChild = leftValue;
}
public void setRight(Node rightValue) {
this.rightChild = rightValue;
}
public Node getRight() {
return rightChild;
}
public Node getLeft() {
return leftChild;
}
}
public static boolean isBalanced(Node root) {
HashSet < Integer > hset = new HashSet < Integer > ();
if (root != null) {
count++;
isBalanced(root.getLeft());
isBalanced(root.getRight());
count--;
if (root.getLeft() == null && root.getRight() == null) {
if (!hset.isEmpty()) {
for (int x: hset) {
if ((x - count) < 0) {
int sum = count - x;
if (sum > 1) {
return false;
}
} else if ((x - count) > 1) {
return false;
}
}
hset.add(count);
} else {
hset.add(count);
}
}
}
return true;
}
public static void main(String[] args) {
Node One = new Node(1);
Node Two = new Node(2);
Node Three = new Node(3);
Node Four = new Node(4);
Node Five = new Node(5);
Node Six = new Node(6);
Node Seven = new Node(7);
Node Eight = new Node(8);
Node Nine = new Node(9);
Node Ten = new Node(10);
Node Eleven = new Node(11);
Five.setLeft(Three);
Five.setRight(Seven);
Three.setLeft(Two);
Three.setRight(Four);
Two.setLeft(One);
Seven.setLeft(Six);
Seven.setRight(Eight);
Eight.setRight(Nine);
Nine.setRight(Ten);
Ten.setRight(Eleven);
System.out.print(isBalanced(Five));
}
}

Binary Tree returning nulls for nodes

I'm trying to build a binary tree recursively for an AI I'm developing.
I try to build a tree but everything comes back null. The language is Java and I'm using Eclipse. Also, I'm on a Mac if that means anything. The tree should be returned as a binary tree with nodes instantiated but without any content.
public class DecisionTree {
//build a generic, empty, tree
//building binary
Root r = new Root();
public void build() //ok
{
Node lhs = new Node();
Node rhs = new Node();
lhs = new Node();
rhs = new Node();
r.lhs = lhs;
r.rhs = rhs;
lhs.parent = r;
rhs.parent = r;
builtRecursion(lhs, 1);
builtRecursion(rhs, 1);
outputTree();
int ctr = 1; //levels of tree
}
public int builtRecursion(Node n, int ctr)
{
Node lhs = new Node();
Node rhs = new Node();
ctr++;
System.out.println("built recursion ctr is " + ctr);
if (ctr > 10)
{
//leaf node
Behaviors behavior = new Behaviors();
Node node = behavior;
n.b = behavior;
return 0;
}
n.lhs = lhs;
n.rhs = rhs;
lhs.parent = n;
rhs.parent = n;
builtRecursion(lhs, ctr);
builtRecursion(rhs, ctr);
return ctr;
}
public void outputTree()
{
if (r != null)
{
System.out.println("Root");
}
outputTreeRecursive(r);
}
public void outputTreeRecursive(Node n)
{
if (n.lhs != null)
{
System.out.println("------------------");
System.out.println("LHS");
outputTreeRecursive(n.lhs);
}
else { System.out.println("LHS is null");}
if (n.rhs != null)
{
System.out.println("-----------------");
System.out.println("RHS");
outputTreeRecursive(n.rhs);
}
else { System.out.println("RHS is null");}
System.out.println("-----------------");
}
}
ROOT CLASSS
package FLINCH;
public class Root extends Node {
Node lhs = new Node();
Node rhs = new Node();
}
NODE CLASS
package FLINCH;
import java.util.ArrayList;
import java.util.LinkedList;
public class Node {
Node lhs = null;
Node rhs = null;
Node parent = null;
Decider d = new Decider(this);
Behaviors b = null;
public LinkedList getSuccessors()
{
LinkedList list = new LinkedList();
list.add(lhs);
list.add(rhs);
return list;
}
}
OUTPUT
GetAction Running
Iterating through open list
Size of open list is 1
Peeked openLIst size is 1
Peeking throguh open list
Popping Open List
LHS is null
RHS is null
Number of children is 2
Children equals 2
Decider childrens loop
Child node is null
Iterating through children
Exception in thread "main" java.lang.NullPointerException
at FLINCH.A_Star_Search.search3(A_Star_Search.java:81)
at FLINCH.Soldier.search_behavior(Soldier.java:28)
at FLINCH.Main.getAction(Main.java:54)
at tests.GameVisualSimulationTest.main(GameVisualSimulationTest.java:52)
I hope this helps...
I have a piece of code which you can use for BinaryTree
public class BinarySearchTree {
public static Node root;
public BinarySearchTree(){
this.root = null;
}
public void insert(int id){
Node newNode = new Node(id);
if(root==null){
root = newNode;
return;
}
Node current = root;
Node parent = null;
while(true){
parent = current;
if(id < current.data){
current = current.left;
if(current==null){
parent.left = newNode;
return;
}
}else{
current = current.right;
if(current==null){
parent.right = newNode;
return;
}
}
}
}
public boolean find(int id){
Node current = root;
while(current!=null){
if(current.data==id){
return true;
}else if(current.data > id){
current = current.left;
}else{
current = current.right;
}
}
return false;
}
public boolean delete(int id){
Node parent = root;
Node current = root;
boolean isLeftChild = false;
while(current.data!=id){
parent = current;
if(current.data > id){
isLeftChild = true;
current = current.left;
}else{
isLeftChild = false;
current = current.right;
}
if(current ==null){
return false;
}
}
//if i am here that means we have found the node
//Case 1: if node to be deleted has no children
if(current.left==null && current.right==null){
if(current==root){
root = null;
}
if(isLeftChild ==true){
parent.left = null;
}else{
parent.right = null;
}
}
//Case 2 : if node to be deleted has only one child
else if(current.right==null){
if(current==root){
root = current.left;
}else if(isLeftChild){
parent.left = current.left;
}else{
parent.right = current.left;
}
}
else if(current.left==null){
if(current==root){
root = current.right;
}else if(isLeftChild){
parent.left = current.right;
}else{
parent.right = current.right;
}
}else if(current.left!=null && current.right!=null){
//now we have found the minimum element in the right sub tree
Node successor = getSuccessor(current);
if(current==root){
root = successor;
}else if(isLeftChild){
parent.left = successor;
}else{
parent.right = successor;
}
successor.left = current.left;
}
return true;
}
public Node getSuccessor(Node deleleNode){
Node successsor =null;
Node successsorParent =null;
Node current = deleleNode.right;
while(current!=null){
successsorParent = successsor;
successsor = current;
current = current.left;
}
//check if successor has the right child, it cannot have left child for sure
// if it does have the right child, add it to the left of successorParent.
// successsorParent
if(successsor!=deleleNode.right){
successsorParent.left = successsor.right;
successsor.right = deleleNode.right;
}
return successsor;
}
public void display(Node root){
if(root!=null){
display(root.left);
System.out.print(" " + root.data);
display(root.right);
}
}
public static void printInOrder(Node root){
if(root == null){
return;
}
printInOrder(root.left);
System.out.print(root.data+" ");
printInOrder(root.right);
}
public static void printPreOrder(Node root){
if(root == null){
return;
}
System.out.print(root.data+" ");
printPreOrder(root.left);
printPreOrder(root.right);
}
public static void printPostOrder(Node root){
if(root == null){
return;
}
printPostOrder(root.left);
printPostOrder(root.right);
System.out.print(root.data+" ");
}
public static void main(String arg[]){
BinarySearchTree b = new BinarySearchTree();
b.insert(3);b.insert(8);
b.insert(1);b.insert(4);b.insert(6);b.insert(2);b.insert(10);b.insert(9);
b.insert(20);b.insert(25);b.insert(15);b.insert(16);
System.out.println("Original Tree : ");
b.display(b.root);
System.out.println("");
System.out.println("Check whether Node with value 4 exists : " + b.find(4));
System.out.println("Delete Node with no children (2) : " + b.delete(2));
b.display(root);
System.out.println("\n Delete Node with one child (4) : " + b.delete(4));
b.display(root);
System.out.println("\n Delete Node with Two children (10) : " + b.delete(10));
b.display(root);
System.out.println();
System.out.println("********* Printing In Order *********");
printInOrder(root);
System.out.println();
System.out.println("********* Printing Pre Order *********");
printPreOrder(root);
System.out.println();
System.out.println("********* Printing Post Order *********");
printPostOrder(root);
}
}
class Node{
int data;
Node left;
Node right;
public Node(int data){
this.data = data;
left = null;
right = null;
}
}
when you call your buildRecursion with ctr = 1, you probably mean you want to build a tree with just one extra level and from your comment where you expect to build a leaf node, the condition needs to be modified. in your case the condition should be:
if (ctr == 1)
I made some changes to your function for better output:
public void builtRecursion(Node n, int ctr)
{
System.out.println("built recursion ctr is " + ctr);
if (ctr == 1)
{
//leaf node
Behaviors behavior = new Behaviors();
n.b = behavior;
return;
}
Node lhs = new Node();
Node rhs = new Node();
n.lhs = lhs;
n.rhs = rhs;
lhs.parent = n;
rhs.parent = n;
builtRecursion(lhs, ctr--);
builtRecursion(rhs, ctr--);
}
About the problem regarding I try to build a tree but everything comes back null, well in your outputTree and outputRecursion you don't print anything instead of "-----", "LHS", "RHS" and in case you reach where there is no left or right node you will print "LHS/RHS is null" but you should know that with a leaf node this is an accepted behavior so when you reach the leaf nodes you should print their values instead. However you can change the outputTreeRecursive to the following:
public void outputTreeRecursive(Node n)
{
if (n.lhs != null)
{
System.out.println("------------------");
System.out.println("LHS");
outputTreeRecursive(n.lhs);
}
else {
System.out.println("LHS is null");
if(n.b != null)
System.out.println("Leaf node");
}
if (n.rhs != null)
{
System.out.println("-----------------");
System.out.println("RHS");
outputTreeRecursive(n.rhs);
}
else {
System.out.println("RHS is null");
if(n.b != null)
System.out.println("Leaf node");
}
System.out.println("-----------------");
}
now probably you get better idea about your tree

Null Pointer while Traversing through Binary Tree

I was doing an assignment in which I'm supposed to create a binary tree and define given functions from its abstract superclass (AbstractBinaryTree.java).
While working on a function called getNumbers() which is basically going to traverse through the whole tree whilst adding values from each node to an array list which it returns. There seems to be a null pointer in one of my if statements.
AbstractBinaryTree.java
import java.util.ArrayList;
public abstract class AbstractBinaryTree
{
protected Node root;
protected int sizeOfTree;
public AbstractBinaryTree()
{
root = null;
sizeOfTree = 0;
}
public int size(){ return sizeOfTree; }
/** compute the depth of a node */
public abstract int depth(Node node);
/** Check if a number is in the tree or not */
public abstract boolean find(Integer i);
/** Create a list of all the numbers in the tree. */
/* If a number appears N times in the tree then this */
/* number should appear N times in the returned list */
public abstract ArrayList<Integer> getNumbers();
/** Adds a leaf to the tree with number specifed by input. */
public abstract void addLeaf(Integer i);
/** Removes "some" leaf from the tree. */
/* If the tree is empty should return null */
public abstract Node removeLeaf();
// these methods are only needed if you wish
// use the TreeGUI visualization program
public int getheight(Node n){
if( n == null) return 0;
return 1 + Math.max(
getheight(n.getLeft()) , getheight(n.getRight())
);
}
public int height(){ return getheight(root); }
}
Node.java File.
public class Node{
protected Integer data;
protected Node left;
protected Node right;
public Node(Integer data)
{
this.data = data;
this.left = this.right = null;
}
public Node(Integer data, Node left, Node right){
this.data = data;
this.left = left;
this.right = right;
}
public Integer getData(){ return this.data; }
public Node getLeft(){ return this.left; }
public Node getRight(){ return this.right; }
public void setLeft(Node left){ this.left = left; }
public void setRight(Node right){ this.right = right; }
public void setData(Integer data){ this.data = data; }
}
BinaryTree.java
import java.util.ArrayList;
import java.util.*;
// Student Name: Adrian Robertson
// Student Number: 101020295
//
// References: Collier, R. "Lectures Notes for COMP1406C- Introduction to Computer Science II" [PDF documents]. Retrieved from cuLearn: https://www.carleton.ca/culearn/(Winter2016).//
// References: http://codereview.stackexchange.com/questions/13255/deleting-a-node-from-a-binary-search-tree
// http://www.algolist.net/Data_structures/Binary_search_tree/Removal
// http://www.geeksforgeeks.org/inorder-tree-traversal- without-recursion-and-without-stack/
public class BinaryTree extends AbstractBinaryTree
{
protected Node root = new Node(12);
public static BinaryTree create()
{
BinaryTree tempTree = new BinaryTree();
//creating all the nodes
Node temp10 = new Node(10);
Node temp40 = new Node(40);
Node temp30 = new Node(30);
Node temp29 = new Node(29);
Node temp51 = new Node(51);
Node temp61 = new Node(61);
Node temp72 = new Node(72);
Node temp31 = new Node(31);
Node temp32 = new Node(32);
Node temp42 = new Node(42);
Node temp34 = new Node(34);
Node temp2 = new Node(2);
Node temp61x2 = new Node(61);
Node temp66 = new Node(66);
Node temp3 = new Node(3);
Node temp73 = new Node(73);
Node temp74 = new Node(74);
Node temp5 = new Node(5);
//setting up the tree
if (tempTree.root.getData() == null)
{
tempTree.root.setData(12);
tempTree.root.setLeft(temp10);
tempTree.root.setRight(temp40);
}
temp10.setLeft(temp30);
temp30.setRight(temp29);
temp29.setRight(temp51);
temp51.setLeft(temp61);
temp51.setRight(temp72);
temp40.setLeft(temp31);
temp31.setLeft(temp42);
temp31.setRight(temp34);
temp34.setLeft(temp61x2);
temp61x2.setLeft(temp66);
temp61x2.setRight(temp73);
temp40.setRight(temp32);
temp32.setRight(temp2);
temp2.setLeft(temp3);
temp3.setRight(temp74);
temp74.setLeft(temp5);
return tempTree;
}
public int depth(Node node)
{
Node current = this.root;
int counter = 1;
while(node != current)
{
if (node.getData() > current.getData())
current = current.getRight();
if (node.getData() < current.getData())
current = current.getLeft();
}
return counter;
}
public boolean find(Integer i)
{
boolean found = false;
Node current = this.root;
if (i == current.getData())
found = true;
while (i != current.getData())
{
if (i > current.getData())
current = current.getRight();
if (i < current.getData())
current = current.getLeft();
if (i == current.getData())
found = true;
}
return found;
}
public ArrayList<Integer> getNumbers()
{
ArrayList<Integer> temp = new ArrayList<Integer>();
Node current = this.root;
Node Pre = new Node(null);
while (current.getData() != null )
{
if (current.getLeft().getData() == null)
{
temp.add(current.getData());
current = current.getRight();
}
else
{
/* Find the inorder predecessor of current */
Pre = current.getLeft();
while(Pre.getRight() != null && Pre.getRight() != current)
Pre = Pre.getRight();
/* Make current as right child of its inorder predecessor */
if (Pre.getRight() == null)
{
Pre.setRight(current);
current = current.getLeft();
}
/* Revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */
else
{
Pre.setRight(null);
temp.add(current.getData());
current = current.getRight();
}/* End of if condition Pre.right == NULL */
}/* End of if condition current.left == NULL*/
}/*End of while */
Collections.sort(temp);
return temp;
}
public void addLeaf(Integer i)
{
insert(this.root, i);
}
public static void insert(Node node, int value) //insert a node Based on provided argument where node is the root of tree
{
if (node == null)
{
Node first = new Node(value);
node = first;
}
else if (value < node.getData())
{
if (node.left != null)
{
insert(node.left, value);
}
else
{
System.out.println(" > Inserted " + value + " to left of node " + node.getData());
Node newNode = new Node(value);
node.left = newNode;
}
}
else if (value > node.getData())
{
if (node.right != null)
{
insert(node.right, value);
}
else
{
System.out.println(" > Inserted " + value + " to right of node " + node.getData());
Node newNode = new Node(value);
node.right = newNode;
}
}
}
public Node removeLeaf()
{
Node tempA = new Node(61); //create a new node with that value
deleteNodeBST(this.root, 61); //delete the node containing that leaf value
return tempA; //return the copy of that node
}
//delete given node with given value
public boolean deleteNodeBST(Node node, int data) {
ArrayList<Integer> temp = this.getNumbers();
if (node == null) {
return false;
}
if (node.getData() == data) {
if ((node.getLeft() == null) && (node.getRight() == null)) {
// leaf node
node = null;
return true;
}
if ((node.getLeft() != null) && (node.getRight() != null)) {
// node with two children
node.setData(temp.get(0));
return true;
}
// either left child or right child
if (node.getLeft() != null) {
this.root.setLeft(node.getLeft());
node = null;
return true;
}
if (node.getRight() != null) {
this.root.setRight(node.getRight());
node = null;
return true;
}
}
this.root = node;
if (node.getData() > data) {
return deleteNodeBST(node.getLeft(), data);
} else {
return deleteNodeBST(node.getRight(), data);
}
}
public static void main(String args[])
{
BinaryTree myTree = new BinaryTree();
myTree.create();
System.out.println(myTree.getNumbers());
}
}
The create function creates a binary tree and returns that binary tree. This is the predefined binary tree that I was supposed to create according to assignment guidelines. I understand that the tree values are not organised properly as they would be in a proper binary tree. Is that was causes the null pointer during traversal? Cause the traversal is taylored to work for a proper Binary tree.
In class BinaryTree, you initialize the left and right of your root node only if the haven't data. But the root node is create with data...
You should invert the condition in :
//setting up the tree
if (tempTree.root.getData() == null)
And add a test in getNumbers() :
if (current.getLeft() == null || current.getLeft().getData() == null)
In the BinaryTree class, getNumbers() method and while loop. Maybe your problem is here:
if (current.getLeft().getData() == null) {
temp.add(current.getData());
current = current.getRight();
}
When you call current.getLeft(), it will return null when the left Node is null. And then, you call getData() it will throw a NullPointerException. If you're not sure that it always not null check it before you call any methods of it. Example you can change the if statement to:
if (current.getLeft() != null && current.getLeft().getData() == null) {
temp.add(current.getData());
current = current.getRight();
}
Or:
Node left = current.getLeft();
if (left == null) {
//TODO something here
} else if (left.getData() == null) {
temp.add(current.getData());
current = current.getRight();
}
Please update your getNumbers - method accordingly,
You need to put right checks before work with reference type.
public ArrayList<Integer> getNumbers()
{
ArrayList<Integer> temp = new ArrayList<Integer>();
Node current = this.root;
Node Pre = new Node(null);
while (current != null && current.getData() != null ) // Fix here... Add : current != null
{
if (current.getLeft() != null && current.getLeft().getData() == null) // Fix here... Add : current.getLeft() != null
{
temp.add(current.getData());
current = current.getRight();
}
else
{
/* Find the inorder predecessor of current */
Pre = current.getLeft();
while(Pre != null && Pre.getRight() != null && Pre.getRight() != current) // Fix here... Add : Pre != null
Pre = Pre.getRight();
/* Make current as right child of its inorder predecessor */
if (Pre != null && Pre.getRight() == null) // Fix here... Add : Pre != null
{
Pre.setRight(current);
current = current.getLeft();
}
/* Revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */
else
{
if(Pre != null){ // Fix here... Add : Pre != null
Pre.setRight(null);
}
temp.add(current.getData());
current = current.getRight();
}/* End of if condition Pre.right == NULL */
}/* End of if condition current.left == NULL*/
}/*End of while */
Collections.sort(temp);
return temp;
}

Convert Binary Search Tree to Doubly Linked List - not working

Solution i am pasting comes from this Geek URL
Its written in C, so i tried converting it in JAVA as below - (please do correct me if m wrong, i am not c/c++ person)
Program
// A simple recursive function to convert a given Binary tree to Doubly
// Linked List
// root --> Root of Binary Tree
// head --> Pointer to head node of created doubly linked list
public void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes head)
{
if(root == null)
return;
// Initialize previously visited node as NULL. This is
// declared outside the recursive function so that the same value
// is accessible in all recursive calls
prev = null;
// Recursively convert left subtree
BinaryTree2DoubleLinkedList(root.getLeft(), head);
//set head of LL if not set
if(orgHead == null)
orgHead = root;
// Now convert this node
if (prev == null)
head = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
BinaryTree2DoubleLinkedList(root.getRight(), head);
}
Tree In Consideration
10
/ \
5 15
/ \ / \
2 7 12 18
/
1
/
0
Problem
This program returns output :
0 1 2 5 7 10 15 18
As you can see, 12 is missing from the code.I tried to dry run it many times but still not able to find out the real issue.....I tried searching for different solutions but most of them traverse in the part-converted-LL which increases the time complexity.
In original C code function prototype is following:
void BinaryTree2DoubleLinkedList(node *root, node **head)
**head mean double pointer, head value can be changed within function using *head. In java you can't modify function parameter because they are always copied, but you can modify array element.
So please try following code:
BTNode prev;
void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes[] head)
{
// Base case
if (root == null) return;
// Initialize previously visited node as NULL. This is
// static so that the same value is accessible in all recursive
// calls
// Recursively convert left subtree
BinaryTree2DoubleLinkedList(roor.getLeft(), head);
// Now convert this node
if (prev == null)
head[0] = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
BinaryTree2DoubleLinkedList(root.getRight(), head);
}
Initial call should look like:
BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
// result is in head[0]
To avoid ugly allocation for head element better to make additional function like following:
BTNodes BinaryTree2DoubleLinkedList(BTNodes root) {
BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
return head[0];
}
Converting Binary Search tree into Doubly Linked List is kind of easy task if we use left and right fields of Node.
Recursion helps us here.
First, go down till the left node. Assign the left most leaf node as prev and also as head of list.
Once control come back from leaf node to its parent, assign current node i.e. parent of left node as right of prev and left of current node as leaf node.
Same is goes for right leaf child of current node.
Once we are out of complete recursion, we will have our doubly linked list, with listHead and listTail.
{
Node prev = null;
Node listHead = null;
Node listTail = null;
public void convertToList(Node node)
{
if(node == null)
return;
convertToList(node.left);
if(listHead == null)
listHead = node;
if(prev == null)
prev = node;
else
{
node.left = prev;
prev.right = node;
}
prev = node;
convertToList(node.right);
if(node.right == null)
listTail = node;
}
public void printList()
{
Node node = listHead;
System.out.println("Doubly Linked List from Head: ");
while(node!= null)
{
System.out.print(node.data+" ");
node = node.right;
}
}
public void printListFromTail()
{
Node node = listTail;
System.out.println("Doubly Linked List from Tail: ");
while(node!= null)
{
System.out.print(node.data+" ");
node = node.left;
}
}
}
For any google visitor, i worked out a way to avoid head[0] - (this might pose problems if the program is called through different object for different trees, as head[0] may get overwritten)
Here is the implementation :
Trick is to remove prev = null; from the code and initialize tempHead = null and prev = null in the calling function, not in recursive call.
void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes tempHead)
{
// Base case
if (root == null) return; //optional, not needed in fact
// Recursively convert left subtree
if(root.getLeft() != null) //purely to reduce number of traversed node
BinaryTree2DoubleLinkedList(root.getLeft(), tempHead);
//set Original Head of the List, this would be leftmost
//leaf in the tree
if(orgHead == null)
orgHead = root;
// Now convert this node
if (prev == null)
tempHead = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
if(root.getRight() != null) //purely to reduce number of traversed node
BinaryTree2DoubleLinkedList(root.getRight(), tempHead);
}
Other helper Details :
Initial call :
BinaryTree2DoubleLinkedList(bst.root,tempHead); //root and null value
Traverse List
printList(orgHead); //pass original head to print function
Complexity :
Time = Space : O(n)
public void ConverttoList(Node root){
Node top = root;
top.left = GetLeftNode(top.left);
top.right = GetRightNode(top.right);
top.left.right= top;
top.right.left= top;
Node leftmost = top.left;
while(leftmost.left!=null){
leftmost = leftmost.left;
}
while(leftmost!= null) {
System.out.printf(leftmost.Data + "->");
leftmost = leftmost.right;
}
}
public Node GetLeftNode(Node root){
if(root.left == null){
return root;
}
else{
Node startnode = GetLeftNode(root.left);
startnode.right = root;
root.left = startnode;
root.right = GetRightNode(root.right);
root.right.left = root;
Node rightmost=root.right;
while (rightmost.right!=null){
rightmost=rightmost.right;
}
return rightmost;
}
}
public Node GetRightNode(Node root){
if(root.left == null){
return root;
}
else{
Node startnode = GetLeftNode(root.left);
startnode.right = root;
root.left = startnode;
root.right = GetRightNode(root.right);
root.right.left = root;
Node leftmost=root.left;
while (leftmost.left!=null){
leftmost=leftmost.left;
}
return leftmost;
}
}
// bst to dll will generate a sorted dll
public class TreeToDLL {
public static void main(String args[]){
TreeNode t = new TreeNode(5);
TreeNode t3 = new TreeNode(3);
TreeNode t1 = new TreeNode(1);
TreeNode t7 = new TreeNode(7);
TreeNode t9 = new TreeNode(9);
TreeNode t8 = new TreeNode(8);
t.setLeft(t3);
t3.setLeft(t1);
t.setRight(t7);
t7.setRight(t9);
t9.setLeft(t8);
DllNode dll = convert(t);
dll.print();
}
static class DllNode{
int data;
DllNode next;
DllNode prev;
public DllNode(int data) {
this.data = data;
}
public DllNode() {
}
public int getData() {
return data;
}
public DllNode getPrev() {
return prev;
}
public void setPrev(DllNode prev) {
this.prev = prev;
}
public void setData(int data) {
this.data = data;
}
public DllNode getNext() {
return next;
}
public void setNext(DllNode next) {
this.next = next;
}
public void print(){
DllNode t = this;
while(t!=null){
System.out.print(t.getData()+"->");
t = t.getNext();
}
}
}
static class TreeNode{
int data;
TreeNode left;
TreeNode right;
public TreeNode(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public TreeNode getLeft() {
return left;
}
public TreeNode setLeft(TreeNode left) {
this.left = left;
return this;
}
public TreeNode getRight() {
return right;
}
public TreeNode setRight(TreeNode right) {
this.right = right;
return this;
}
}
private static DllNode convert(TreeNode t){
DllNode d =convert(t,new PreviousDLLNode());
while(d.prev!=null){
d = d.prev;
}
return d;
}
private static DllNode convert(TreeNode t, PreviousDLLNode d){
if(t==null) return null;
convert(t.getLeft(),d);
DllNode dn = new DllNode(t.getData());
if(d.val!=null){
d.val.setNext(dn);
}
dn.setPrev(d.val);
d.val = dn;
convert(t.getRight(),d);
return dn; // this node will be in the middle of the dll.
}
private static class PreviousDLLNode{
DllNode val;
}
}
I solved my problem inserting treenodes sorted in order in a DLL like that:
I added in my netBeans package the DoubleLinkedList and BinarySearchTree classes needed (including the TreeNode and the DoubleNode etc) and
I modified the BinarySearchTree as shown below:
public class BinarySearchTree {
DoubleLinkedList dL;
TreeNode root;
public BinarySearchTree() {
this.root = null;
this.dL=new DoubleLinkedList();
}
public void
tree2DList(TreeNode TN) {
if (TN == null) {
return ;
} else {
tree2DList(TN.left);
dL.insertLast((YourClassOfObjects)TN.getItem());
tree2DList(TN.right);
}
return;
}
I added a DoubleLinkedList field which I initialized in the default constructor of BST, calling the default constructor of DLL and I created the recursive method below, inspired from and following inOrderTraversal for the sorted input of tree nodes in the DLL

Categories

Resources