user3064423
user3064423

Reputation: 1

Null pointer error. Binary search tree program

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

Answers (1)

rolfl
rolfl

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

Related Questions