Reputation: 1
I'm trying to program a binary tree. Everything works fine except when I try to delete the root node.
Returning the following error. I have no idea how to fix this. Please help.
Every other function like Add, Statistics, Balance, ect works fine. Only when I try to perform the Delete on the root node the program returns.
Exception in thread "main" java.lang.NullPointerException
at TreeClass$BinarySearchTree.Delete(TreeClass.java:147)
at TreeClass$BinarySearchTree.fnHandler(TreeClass.java:292)
at TreeClass.main(TreeClass.java:341)
However, delete works on other nodes in the tree. Only runs into problems with the root node. Here's my code
import java.util.*;
public class TreeClass
{
//--------------------------------------------------------------
static Scanner scanner = new Scanner(System.in);
static BinarySearchTree BST = new BinarySearchTree();
//--------------------------------------------------------------
public static class TreeNode
{
TreeNode Parent;
TreeNode LChild;
TreeNode RChild;
Integer Data;
public TreeNode(int cbData)
{
this.Data = cbData;
this.LChild = null;
this.RChild = null;
this.Parent = null;
}
public void SetParent(TreeNode parent)
{
this.Parent = parent;
}
}
public static class BinarySearchTree
{
int size;
TreeNode Root;
public BinarySearchTree()
{
this.size = 0;
this.Root = null;
}
public void Allocate(TreeNode node, ArrayList<Integer> DataList)
{
if (node.LChild != null)
Allocate(node.LChild, DataList);
DataList.add(node.Data);
if (node.RChild != null)
Allocate(node.RChild, DataList);
}
public void Add(int cbData)
{
TreeNode temp = null;
TreeNode node = new TreeNode(cbData);
if(this.size == 0)
{
this.Root = node;
}
else
{
temp = this.Root;
while(temp != null)
{
if(cbData > temp.Data)
{
if(temp.RChild == null)
{
temp.RChild = node;
node.Parent = temp;
break;
}
temp = temp.RChild;
}
else if(cbData < temp.Data)
{
if(temp.LChild == null)
{
temp.LChild = node;
node.Parent = temp;
break;
}
temp = temp.LChild;
}
else
{
//System.out.printf("[Error] %d already exists!\n", cbData);
return;
}
}
}
if(size == 0)
System.out.printf("[Success] %d has been added as root\n", node.Data);
else
System.out.printf("[Success] %d has been added - Parent: %d\n", node.Data, node.Parent.Data);
++this.size;
}
public void AddReBalance(int[] List, int min, int max)
{
if(min <= max)
{
int current = (max+min)/2;
Add(List[current]);
AddReBalance(List, min, current-1);
AddReBalance(List, current+1, max);
}
}
public void Delete(int cbData)
{
TreeNode temp = null;
if(this.size > 0)
{
temp = this.Root;
while(temp != null)
{
if(cbData > temp.Data)
temp = temp.RChild;
else if(cbData < temp.Data)
temp = temp.LChild;
else
{
System.out.printf("[Success] %d found and deleted!\n", cbData);
if(temp.LChild != null)
{
temp.LChild.Parent = temp.Parent;
if(temp == temp.Parent.RChild)
temp.Parent.RChild = temp.LChild;
else if(temp == temp.Parent.LChild)
temp.Parent.LChild = temp.LChild;
}
else if(temp.RChild != null)
{
temp.RChild.Parent = temp.Parent;
if(temp == temp.Parent.LChild)
temp.Parent.LChild = temp.RChild;
else if(temp == temp.Parent.RChild)
temp.Parent.RChild = temp.RChild;
}
else
{
if(temp == temp.Parent.LChild)
temp.Parent.LChild = null;
else if(temp == temp.Parent.RChild)
temp.Parent.RChild = null;
temp.Parent = null;
}
--this.size;
return;
}
}
}
System.out.printf("[Error] %d not found!\n", cbData);
}
public int Find(int cbData)
{
int Level = 0;
TreeNode temp = this.Root;
while(temp != null)
{
if(cbData > temp.Data)
{
temp = temp.RChild;
++Level;
}
else if(cbData < temp.Data)
{
temp = temp.LChild;
++Level;
}
else if(cbData == temp.Data)
{
return ++Level;
}
}
return -1;
}
public void Rebalance()
{
int[] cbList = new int[this.size];
ArrayList<Integer> DataList = new ArrayList();
Allocate(this.Root, DataList);
for(int i = 0; i < DataList.size(); ++i)
cbList[i] = DataList.get(i);
this.size = 0;
if(cbList.length > 0)
AddReBalance(cbList, 0, cbList.length-1);
else
System.out.print("[Error] You do not have any nodes to balance!\n");
}
public void DisplayContent(TreeNode node)
{
ArrayList<Integer> DataList = new ArrayList();
Allocate(this.Root, DataList);
System.out.printf("Tree Content: ");
for(int i = 0; i < DataList.size(); ++i)
System.out.printf("%d ", DataList.get(i));
System.out.printf("\n");
}
public void GetPathData(TreeNode node, ArrayList<Integer> DepthList, int Level)
{
++Level;
if(node.RChild != null | node.LChild != null)
{
if (node.LChild != null)
GetPathData(node.LChild, DepthList, Level);
if (node.RChild != null)
GetPathData(node.RChild, DepthList, Level);
}
else
{
DepthList.add(Level);
Level = 0;
}
}
public void DisplayStats()
{
int Level = 0, Max = 0, Min = 0;
ArrayList<Integer> DList = new ArrayList();
GetPathData(this.Root, DList, Level);
for(int i = 0; i < DList.size(); ++i)
{
int TempPath = DList.get(i);
if(i == 0)
{
Min = TempPath;
Max = TempPath;
}
else
{
if(Min > TempPath)
Min = TempPath;
if(Max < TempPath)
Max = TempPath;
}
}
System.out.printf("Root Data: %d\nItem Count: %d\nShortest Path: %d" +
"\nLongest Path: %d\n\n", this.Root.Data, this.size, Min, Max);
}
public boolean fnHandler(int cbIn)
{
int cbInItem = 0;
int cbTempRetn = 0;
boolean retn = false;
switch(cbIn)
{
case 1:
System.out.printf("Input an integer to add: ");
cbInItem = scanner.nextInt();
Add(cbInItem);
break;
case 2:
System.out.printf("Input an integer to delete: ");
cbInItem = scanner.nextInt();
Delete(cbInItem);
break;
case 3:
System.out.printf("Input an integer to find:");
cbInItem = scanner.nextInt();
cbTempRetn = BST.Find(cbInItem);
if(cbTempRetn == -1)
System.out.printf("[Error] This item was not found!\n");
else
System.out.printf("[Success] Item was found on level: %d\n", cbTempRetn);
break;
case 4:
BST.Rebalance();
System.out.printf("[Success] Tree has been balanced!\n");
break;
case 5:
BST.DisplayContent(BST.Root);
break;
case 6:
BST.DisplayStats();
break;
case 7:
retn = true;
System.out.printf("[Exitting...]\n");
break;
}
return retn;
}
}
public static void main(String[] args)
{
int cbInput = 0;
boolean exit = false;
while(exit == false)
{
System.out.printf("\n1. Add Entry - 2. Delete Item - 3. Find Item - 4. Balance Tree"
+ "\n5. List Data - 6. Statistics - 7. Exit\n\nInput: ");
cbInput = scanner.nextInt();
exit = BST.fnHandler(cbInput);
}
}
}
Upvotes: 0
Views: 356
Reputation: 17705
You have a bigger problem than just the null-pointer exception....
When you delete a node you are trying to take the remaining 'child' nodes and re-attach them to the parent of the removed node:
if(temp.LChild != null)
{
temp.LChild.Parent = temp.Parent;
if(temp == temp.Parent.RChild)
temp.Parent.RChild = temp.LChild;
else if(temp == temp.Parent.LChild)
temp.Parent.LChild = temp.LChild;
}
And, in your case, the temp.Parent is null (because it is the root node), and thus you get the NPE on (lines like... not necessarily this exact one):
temp == temp.Parent.RChild
Unfortunately you have some problems here....
When you delete a node in the general case (i.e. not the root) it is possible that the parent already has child nodes on the other leg, so you cannot attach both of the deleted node's children to the parent....
... this is more complicate to explain than is easy in a comment, but, bottom line is that you delete code is deleting more than just a node, it is deleting the node and all of the children on one of it's legs.
So, when you work-around the null Parent, you will find you have other problems.
Upvotes: 2