简体   繁体   English

二叉树:方法删除子树

[英]Binary tree: method remove subtree

I had an unordered Binary tree and I had to do a method that remove the subtree of root x. 我有一个无序的二叉树,我不得不做一个删除根x的子树的方法。 If the element x is present several times in the binary tree, the method remove only one of the subtree of root x (the first it finds). 如果元素x在二叉树中多次出现,则该方法仅删除根x中的一个子树(它找到的第一个子树)。 If the deletion was performed, returns true. 如果执行了删除,则返回true。 If the element x is not present in the binary tree, returns false. 如果元素x不存在于二叉树中,则返回false。 So the method is: 所以方法是:

    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;
    }
}

I do not know how to start, does anyone have any idea? 我不知道如何开始,有没有人有任何想法? Even pseudocode.. Thanks! 甚至伪代码..谢谢!

Should go something like this.... 应该像这样......

  • find node N that contains value X 找到包含值X的节点N.
  • if N is a leaf, remove the leaf 如果N是叶子,则移除叶子
  • if N is a parent, 如果N是父母,

      removeNodes(N.left); removeNodes(N.right); remove(N); 
  • repeat until you hit a leaf 重复,直到你击中一片叶子

      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() is a wrapper around the recursive removeNodes(); removeSubtree()是递归removeNodes()的包装器;

EDIT: ok so to clarify your mistery. 编辑:好的,以澄清你的错误。 Presume we have this tree 假设我们有这棵树

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

Now, presume you call removeSubtree(5, root); 现在,假设你调用removeSubtree(5,root);

It will traverse the tree until it hits node (a) - the first 5 on the left. 它将遍历树,直到它到达节点(a) - 左边的前5个。 The way your current code is written you will do this: it will find the node with value X (5); 编写当前代码的方式是:它将找到值为X(5)的节点; then for all his left and right subchildren it will look for value 5. 然后,对于他所有的左右子孙,它将寻找值5。

Lets focus on this 让我们关注这一点

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

This is what you should get after calling removeSubtree(5, root); 这是调用removeSubtree(5,root)后应该得到的; In other words, look at the subtree that is supposed to be deleted after finding the first node with value 5 and deleting it's children 换句话说,查找在找到值为5的第一个节点并删除它的子节点后应该删除的子树

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

But your code will subsequently look for values 5 to delete in that subtree. 但是,您的代码随后会在该子树中查找要删除的值5。 That is why you need a general-purpose deleteSubtree() routine which will traverse the tree and delete everything it finds. 这就是为什么你需要一个通用的deleteSubtree()例程,它将遍历树并删除它找到的所有内容。 Your removeSubtree(int, node) routine must rely on it or 'inline' it by implementing that mechanism itself. 您的removeSubtree(int,node)例程必须通过实现该机制本身来依赖它或“内联”它。

Right now your code will only delete this 现在你的代码只会删除它

             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

In other words, it will land on node A (first 5), and instead of deleting everything below node (a), it will search for another value 5 below A, find (b) and try to delete it's subtree, matching only node (c). 换句话说,它将落在节点A(前5),而不是删除节点(a)下面的所有内容,它将搜索低于A的另一个值5,找到(b)并尝试删除它的子树,仅匹配节点(C)。

The end result will be this - your code will delete only the three fives and leave you with this 最终结果将是这样 - 您的代码将只删除三个五,并留下你

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

Do you now realize why you cannot use the same function recursively? 你现在意识到为什么你不能递归使用相同的功能? :) at least not in the way you want it right now. :)至少不是你现在想要的方式。 However, you can try this - 但是,你可以尝试这个 -

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

This will effectivelly find the right subtree - node (a), and then call itself to match it's children - nodes 5 and 6 (at depth of node (b)) and thus delete them. 这将有效地找到正确的子树 - 节点(a),然后调用自身以匹配它的子节点 - 节点5和6(节点(b)的深度),从而删除它们。 In any case, you cannot re-use value X in these calls like you used to do with 在任何情况下,您都不能像以前那样在这些调用中重复使用值X.

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

I hope that clarified something :) heh maybe i should teach this :D 我希望澄清一些东西:)嘿,也许我应该教这个:D

I've rewritten this method. 我改写了这个方法。 Now I think it is more correct but I think there is a problem in the instruction node.left = null (same as for the case of right). 现在我认为它更正确但我认为指令node.left = null存在问题(与右边的情况相同)。 In fact, when I go to run this method does not work correctly, if I have a tree made so 事实上,当我去运行时,这种方法无法正常工作,如果我有一棵树就这样做了 在此输入图像描述 and I pass x = 8 , it returns this tree 我传递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