【问题标题】:Deleteing a Node in a Binary tree删除二叉树中的节点
【发布时间】:2014-05-01 02:51:55
【问题描述】:

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

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;


}

基本上我所拥有的是递归运行直到'this'是最右边的节点,然后检查两种情况,'this'是否是叶子,或者'this'是否有左孩子。 (通常与这种算法相关的另一种情况是多余的,因为在找到具有最大值的节点时,我已经尽我所能。)我遇到的问题是让当前节点指向 null或节点左侧的值。

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

我已经设法将问题缩小到我没有返回给定节点值的方法这一事实。现在正在处理这个问题,我们将不胜感激。

【问题讨论】:

    标签: java binary-tree


    【解决方案1】:

    正如其他答案中所建议的,您应该使用迭代方法。

    在 BST 中,最大值是最右边的节点。 因此,请进行扫描并继续前进,直到您遇到空值。 在扫描中跟踪三个节点。 (gpnode,pnode,节点)。 扫描完成后,您将拥有 (gpnode,pnode,null) 现在有2个案例。

    案例一:

    pnode 是一片叶子。所以把边(gpnode,pnode)改成(gpnode,null)

    案例 2:(已编辑

    pnode.lChild 不为空。请注意,pnode.rChild 将为 null,因为此时搜索将终止。 现在将边缘(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;
            }
        }   
    }
    

    【讨论】:

    • 这是不正确的。考虑一棵树,其中最右边的节点有一个左子节点,它是另一个子树的根。复制 pnode.lChild 的值并将其删除意味着您将永远失去所有其他节点。不能复制值和删除,需要维护树的结构。
    • @BrendanMcKee:你是对的。修复了描述和伪代码。感谢您指出。
    【解决方案2】:

    你的想法是对的。您要做的是保留对最右边节点父节点和最右边节点左子节点的引用,这样当您删除它时,您可以附加这两个节点。

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

    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
    }
    

    【讨论】:

    • 你应该小心并且应该知道你在这里真正在做什么。 while(current.right != null &amp;&amp; current.right.right != null)。这看起来没问题,如果订单被更改,那么它将以NULLPointerException 结束。所以最好使用额外的变量并将优化留给编译器:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    相关资源
    最近更新 更多