Java 删除二叉树中的节点

Java 删除二叉树中的节点,java,binary-tree,Java,Binary Tree,我了解二叉搜索树中删除算法的基础,并创建了以下代码来删除树中的最大值 public void DelLargest() { Node<T> del = this; boolean child = this.left.empty(); boolean child2 = this.right.empty(); right.DelLargest(); if(child && child2) this.h

我了解二叉搜索树中删除算法的基础,并创建了以下代码来删除树中的最大值

public void DelLargest()
{
    Node<T> del = this;
    boolean child = this.left.empty();
            boolean child2 = this.right.empty();
    right.DelLargest();
    if(child && child2)
        this.head = null;
    else if(child == true && child2 == false)
        this.head = left;


}
public void delmax()
{
Node del=这个;
boolean child=this.left.empty();
boolean child2=this.right.empty();
对;
if(child和child2)
this.head=null;
else if(child==true&&child2==false)
this.head=左;
}
基本上,我得到的是递归一直运行到“this”是最右边的节点,然后检查两种情况,“this”是一个叶子,还是“this”有一个左边的子节点。(通常与这种算法相关的另一种情况是多余的,因为在查找具有最大值的节点时,我已经尽可能地向右移动了。)我遇到的麻烦是让当前节点指向null或节点左侧的值

注:这就是我的导师所说的“现代”二叉搜索树,其中顶点或“填充”节点和nil或“空”节点是接口节点的两个子类,它们定义了每种类型的特征


我已经设法将问题缩小到没有返回给定节点值的方法这一事实。现在就开始工作,如果您能提供意见,我们将不胜感激。

您的想法是正确的。您要做的是保留对最右侧节点父节点和最右侧节点左子节点的引用,以便在删除它时可以附加这两个节点

这是一个迭代的解决方案。这通常比递归更有效,但是如果您想要递归,您应该能够调整它:

public void delLargest() {
    // get rightmost node's parent
    Node<T> current = root;
    while(current.right != null && current.right.right != null) {
        current = current.right;
    }
    // get the rightmost nodes left node
    Node<T> left = current.right.left;
    // attach the parent and left
    current.right = left;
    // nothing points to the right most node anymore, so it will be garbage collected
}
public void delmax(){
//获取最右侧节点的父节点
节点电流=根;
while(current.right!=null&¤t.right.right!=null){
current=current.right;
}
//从左节点获取最右边的节点
节点左=当前。右。左;
//将父对象附加到左侧
当前。右=左;
//不再有任何东西指向最右边的节点,因此它将被垃圾收集
}

正如另一个答案中所建议的,您应该使用迭代方法

在BST中,最大值是最右边的节点。 所以,做一次扫描,一直向右走,直到找到一个空值。 在扫描中,跟踪三个节点。(gpnode,pnode,node)。 扫描完成后,您将拥有(gpnode、pnode、null) 现在有2例

案例1:

pnode
是一个叶子。因此,将边
(gpnode,pnode)
更改为
(gpnode,null)

案例2:(已编辑)

pnode.lChild
不为空。请注意,
pnode.rChild
将为空,因为搜索将在该点终止。 现在将边缘
(gpnode,pnode)
更改为
(gpnode,pnode.lChild)

以下是伪代码:

public class Node
{
    long key;
    Node lChild;
    Node rChild;
}

public void DelLargest()
{
    Node gpnode = null;
    Node pnode = null;
    Node node = root;
    while(node != null) // keep going right until a null is reached
    {
        gpnode = pnode;
        pnode = node;
        node = node.rChild;
    }
    if(pnode.lChild == null) // its a leaf node So change the edge (gpnode,pnode) to (gpnode,null)
    {
        if(gpnode.lChild == pnode)
        {
            gpnode.lChild = null;
        }
        else
        {
            gpnode.rChild = null;
        }
    }
    else // copy lChild's key to this node and delete lChild
    {
        if(gpnode.lChild == pnode)
        {
            gpnode.lChild = pnode.lChild;
        }
        else
        {
            gpnode.rChild = pnode.lChild;
        }
    }   
}

你应该小心,应该知道你在这里到底在做什么<代码>while(current.right!=null&¤t.right.right!=null)。这看起来没问题,如果更改顺序,则最终会出现
NULLPointerException
。因此,最好使用额外的变量并将优化留给编译器:)这是错误的。考虑一棵树,其中最右边的节点有一个左子树,它是另一个子树的根。复制pnode.lChild的值并将其删除意味着您将永远丢失所有其他节点。你不能复制和删除值,你需要维护树的结构。@BrendanMcKee:你说得对。修复了描述和伪代码。谢谢你指出这一点。