Java I';我试图创建一个方法来查找树中的父节点和祖父母节点,但我一直得到一个nullptr异常

Java I';我试图创建一个方法来查找树中的父节点和祖父母节点,但我一直得到一个nullptr异常,java,binary-tree,binary-search-tree,Java,Binary Tree,Binary Search Tree,我有一个Java任务,我必须创建一个splay树,它需要我找到我正在访问的节点的父节点和祖父母节点。为此,我选择创建一个findParent方法。这是我的节点类 public class Node<T> { public T elem = null; public Node<T> left = null; public Node<T> right = null; public Node(T elem) { this.elem = elem; } p

我有一个Java任务,我必须创建一个splay树,它需要我找到我正在访问的节点的父节点和祖父母节点。为此,我选择创建一个findParent方法。这是我的节点类

public class Node<T>
{
public T elem = null;
public Node<T> left = null;
public Node<T> right = null;

public Node(T elem) {
    this.elem = elem;
}

public String toString() {
    String out = elem.toString();
    out += " [L: "+ (left == null ? "null" : left.elem) + "] ";
    out += " [R: "+ (right == null ? "null" : right.elem) + "] ";
    return out;
    }
}
公共类节点
{
公共T元素=null;
公共节点left=null;
公共节点权限=null;
公共节点(T元素){
this.elem=elem;
}
公共字符串toString(){
String out=elem.toString();
out+=“[L:”+(left==null?“null”:left.elem)+“]”;
out+=“[R:”+(right==null?“null”:right.elem)+“]”;
返回;
}
}
不允许我更改节点类。我的SplayTree类由这些节点组成,在SplayTree类中,我有我的findParent函数

public Node<T> findParent(Node<T> A) {
    Node<T> P = root;
    if (P.left == A || P.right == A) {
        return P;
    } else if (A.elem.compareTo(P.elem) < 0) {
        P = P.left;
    } else {
        P = P.right;
    }
    return null;
}
公共节点findParent(节点A){
节点P=根;
如果(P.left==A | | P.right==A){
返回P;
}如果(A.elem)与(P.elem)<0,则为else{
P=P.左;
}否则{
P=P.右;
}
返回null;
}

为了测试代码,我按顺序在树“50、25、100、5、110、115、75、42、101、112”中输入了以下数字。insert方法遵循常规的BST insert规则,即右边有较大的元素,左边有较小的元素。我使用包含110的节点作为目标测试了findParent方法,因此理论上,它应该返回100作为父节点,为了得到祖父母,我将使用findParent(父节点),它应该返回50,但是我得到了一个nullptr异常。我已经测试了我的insert函数,看看我是否正确地填充了我的树,但是,情况并非如此,因为insert方法工作正常。

您可以递归地执行它,但它可能会在大数据集上使用StackOverFlow异常使执行线程崩溃

public Node<T> findParent(Node<T> node, Node<T> n){
    if(node == null) return null;
    if(node.right == n || node.left == n){
        return node;
    }else{
        Node<T> r = findParent(node.left, n);
        if(r == null){
            r = findParent(node.right, n);
        }
        return r;
    }
}

public Node<T> findParent(Node<T> n){
    if(n == null)
        throw new NullPointerException("arg0 cannot be Null");
    return findParent(root, n);
}
公共节点findParent(节点,节点n){
如果(node==null)返回null;
if(node.right==n | | node.left==n){
返回节点;
}否则{
Node r=findParent(Node.left,n);
if(r==null){
r=findParent(node.right,n);
}
返回r;
}
}
公共节点findParent(节点n){
如果(n==null)
抛出新的NullPointerException(“arg0不能为Null”);
返回findParent(根,n);
}
对于大型数据集,您应该使用某种堆栈机器来遍历所有节点:

public Node<Object> findParent(Node<T> root, Node<T> node){

    Stack<Node<T>> stack = new Stack<>();
    
    stack.push(root);
    
    while(stack.size() > 0){
        Node<T> p = stack.pop();
        if(p.right == node || p.left == node){
            return p;
        }else{
            if(p.left != null){
                stack.push(p.left);
            }else if(p.right != null){
                stack.push(p.right);
            }else{

                
                Node<T> parent = null;
                if(stack.size() > 0)
                    parent = stack.peek();
                
                if(parent == null){
                    break;
                }else if(parent.left == p){
                    if(parent.right != null){
                        stack.push(parent.right);
                    }
                }else if(parent.right == p){
                    stack.pop();
                }
            }
        }
    }

    return null;
}
公共节点findParent(节点根,节点节点){
堆栈=新堆栈();
栈.推(根);
while(stack.size()>0){
Node p=stack.pop();
if(p.right==节点| | p.left==节点){
返回p;
}否则{
如果(p.left!=null){
栈。推(p。左);
}else if(p.right!=null){
栈。推(p。右);
}否则{
节点父节点=null;
if(stack.size()>0)
parent=stack.peek();
如果(父项==null){
打破
}else if(parent.left==p){
if(parent.right!=null){
stack.push(parent.right);
}
}else if(parent.right==p){
stack.pop();
}
}
}
}
返回null;
}
这两种方法都使用您的数据结构进行了测试


在第10行的第二个示例中,如果您返回堆栈,您可以将所有父项都放在一行中

哪一行给出了空指针错误,请编辑您的问题以包含完整错误。另外,我不知道代码中的<代码>根/代码>,但是考虑当你尝试使用<代码> p= P.Lead时发生了什么;code>在之前未设置
left
值的
节点上,这将意味着您将P设置为null,如果您稍后尝试并引用它,则可能会有困难。这是使用
System.out.println(…)进行调试的最佳时机
在分配值之前检查值是什么,以便找出代码中断的原因/位置。