简体   繁体   English

空指针错误。 二进制搜索树程序

[英]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. Add,Statistics,Balance等所有其他功能都可以正常工作。 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);
        }
    }

}

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.Parent为null(因为它是根节点),因此您可以获得NPE(像...这样的行不一定是这样的行):

temp == temp.Parent.RChild

Unfortunately you have some problems here.... 不幸的是你在这里有一些问题....

When you delete a node in the general case (ie 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. 因此,当您处理null Parent时,您会发现还有其他问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM