繁体   English   中英

二叉树:方法删除子树

[英]Binary tree: method remove subtree

我有一个无序的二叉树,我不得不做一个删除根x的子树的方法。 如果元素x在二叉树中多次出现,则该方法仅删除根x中的一个子树(它找到的第一个子树)。 如果执行了删除,则返回true。 如果元素x不存在于二叉树中,则返回false。 所以方法是:

    public class BinaryTree 
{
    protected class Node 
    {
        Integer element;
        Node left;
        Node right;

        Node(int element) 
        {
            this.element = element;
            left = right = null;
        }

        Node(int element, Node left, Node right) 
        {
            this.element = element;
            this.left = left;
            this.right = right;
        }

    protected Node root;

    public BinaryTree() 
    {
        root = null;
    }

    private class BoolNode 
    {
        boolean ft;
        Node nodo;

        BoolNode(boolean ft, Node nodo) 
        {
            this.ft = ft;
            this.nodo = nodo;
        }
    }

    public boolean removeSubtree(int x) 
    {
        BoolNode ris = removeSubtree(x, root);
        //root = ...;
        return ris.ft;
    }

    private BoolNode removeSubtree(int x, Node node) 
    {
        return null;
    }
}

我不知道如何开始,有没有人有任何想法? 甚至伪代码..谢谢!

应该像这样......

  • 找到包含值X的节点N.
  • 如果N是叶子,则移除叶子
  • 如果N是父母,

      removeNodes(N.left); removeNodes(N.right); remove(N); 
  • 重复,直到你击中一片叶子

      private void removeNodes(Node base); //prepare for this when the teacher asks you why it's private // - because you do not want to expose this functionality outside of the class; // the only 'interface' exposed is the wrapper call removeSubtree(...) as the user shouldn't worry about the internal functionality. 

removeSubtree()是递归removeNodes()的包装器;

编辑:好的,以澄清你的错误。 假设我们有这棵树

             1 --- this is root
            / \
           3   7
          / \ / \
     (a) 5  4 3  2  //these branches don't matter right now
        / \
       5   6
      / \  / \
     5  4 3   2

现在,假设你调用removeSubtree(5,root);

它将遍历树,直到它到达节点(a) - 左边的前5个。 编写当前代码的方式是:它将找到值为X(5)的节点; 然后,对于他所有的左右子孙,它将寻找值5。

让我们关注这一点

             1 --- this is root
            / \
           3   7
            \ / \
            4 3  2  

这是调用removeSubtree(5,root)后应该得到的; 换句话说,查找在找到值为5的第一个节点并删除它的子节点后应该删除的子树

         5  -- we should delete all of these starting from here
        / \
       5   6
      / \  / \
     5  4 3   2

但是,您的代码随后会在该子树中查找要删除的值5。 这就是为什么你需要一个通用的deleteSubtree()例程,它将遍历树并删除它找到的所有内容。 您的removeSubtree(int,node)例程必须通过实现该机制本身来依赖它或“内联”它。

现在你的代码只会删除它

             1 --- this is root
            / \
           3   7
          / \ / \
     (a) 5  4 3  2  //these branches don't matter right now
        / \
  (b)  5   6
      / \  / \
(c)  5  4 3   2

换句话说,它将落在节点A(前5),而不是删除节点(a)下面的所有内容,它将搜索低于A的另一个值5,找到(b)并尝试删除它的子树,仅匹配节点(C)。

最终结果将是这样 - 您的代码将只删除三个五,并留下你

             1 --- this is root
            / \
           3   7
          / \ / \
         x  4 3  2  
        / \
       x   6
      / \  / \
     x  4 3   2

你现在意识到为什么你不能递归使用相同的功能? :)至少不是你现在想要的方式。 但是,你可以尝试这个 -

 removeSubtree(node.left.value, node);
 removeSubtree(node.right.value, node);
 removeNode(node);

这将有效地找到正确的子树 - 节点(a),然后调用自身以匹配它的子节点 - 节点5和6(节点(b)的深度),从而删除它们。 在任何情况下,您都不能像以前那样在这些调用中重复使用值X.

 removeSubtree(x, node.left);
 removeSubtree(x, node.right);
 removeNode(node);

我希望澄清一些东西:)嘿,也许我应该教这个:D

我改写了这个方法。 现在我认为它更正确但我认为指令node.left = null存在问题(与右边的情况相同)。 事实上,当我去运行时,这种方法无法正常工作,如果我有一棵树就这样做了 在此输入图像描述 我传递x = 8 ,它返回这棵树 在此输入图像描述

    private BoolNode removeSubtree(Node node, int x) 
{
    if(node == null) 
        return new BoolNode(false, null);
    if(node.element == x) 
        return new BoolNode(true, null);
    BoolNode result = removeSubtree(node.left, x);
    if(result.fatto)
        node.left = null;
    else {
        result = removeSubtree(node.right, x);
        node.right = null;  
    }
    return new BoolNode(result.fatto, node);    
}

暂无
暂无

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

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