我有一个无序的二叉树,我不得不做一个删除根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;
}
}
我不知道如何开始,有没有人有任何想法?甚至伪代码.. 谢谢!
答案 0 :(得分:3)
应该是这样的......
如果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
答案 1 :(得分:0)
我改写了这个方法。现在我认为它更正确,但我认为指令node.left = null
存在问题(与右侧情况相同)。事实上,当我去运行时,这种方法无法正常工作,如果我有一棵树就这样做了
我传递x = 8
,它返回这棵树
答案 2 :(得分:0)
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);
}