我正在尝试删除仅包含零的所有子树。我的代码如下。现在,在根节点上运行removeFailures根本不会修改树(在前后进行预遍历会得到相同的结果)。
我认为这是因为当我说“ root is None”时,实际上并没有修改root,我只是在创建一个可能是root的临时变量名?如果是这种情况,我该如何解决呢?这种推理在Java中行不通吗?
# Ex.
# 4 4
# / \ / \
# 1 3 1 3
# / \ / \ --> / / \
# 0 0 4 6 0 4 6
# /\ /\ / \
# 3 5 0 0 3 5
class TreeNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def removeFailures(root):
if root is None:
return True
removeLeft = removeFailures(root.left)
removeRight = removeFailures(root.right)
if root.data == 0 and removeLeft and removeRight:
root = None
return True
return False
def preorder(root):
print root.data
if root.left:
preorder(root.left)
if root.right:
preorder(root.right)
example = TreeNode(4)
example.left = TreeNode(1, TreeNode(0, TreeNode(3), TreeNode(5)), TreeNode(0, TreeNode(0), TreeNode(0)))
example.right = TreeNode(3, TreeNode(4), TreeNode(6))
preorder(example)
print '*************************'
removeFailures(example)
preorder(example) #TODO
答案 0 :(得分:1)
要检查树中的所有节点是否都包含零,您将必须遍历每个节点。一种可能性是创建一个__iter__
方法来查找树中的所有节点,然后可以应用any
内置函数来确定它们是否都等于零。最后,一种简单的递归方法可以检查左侧和右侧的子级,并在必要时将其删除。
为简化创建树的过程,使用kwargs
来就地构建结构,而无需实现Rotate方法或较长的赋值语句序列:
class Tree:
def __init__(self, **kwargs):
self.__dict__ = {i:kwargs.get(i) for i in ['left', 'right', 'val']}
def __iter__(self):
yield self.val
yield from ([] if self.left is None else self.left)
yield from ([] if self.right is None else self.right)
@staticmethod
def remove_empty_trees(_t):
if not any(_t):
return None
_t.remove_trees()
return _t
def remove_trees(self):
if not any([] if self.left is None else self.left):
self.left = None
else:
self.left.remove_trees()
if not any([] if self.right is None else self.right):
self.right = None
else:
self.right.remove_trees()
# 4
# / \
# 1 3
# / \ / \
# 0 0 4 6
# /\ /\
# 3 5 0 0
t = Tree(val=4, left=Tree(val=1, left=Tree(val=0, left=Tree(val=3), right=Tree(val=5)), right=Tree(val=0, left=Tree(val=0), right=Tree(val=0))), right=Tree(val=3, left=Tree(val=4), right=Tree(val=6)))
new_tree = Tree.remove_empty_trees(t)
print(print(new_tree.left.right))
输出:
None
要处理整个树包含零个节点的情况,staticmethod
提供了额外的检查。
答案 1 :(得分:0)
在子节点上递归调用removeFailures()
后,如果已成功删除它们,则必须将它们设置为None
:
def removeFailures(root):
if root is None:
return True
removeLeft = removeFailures(root.left)
removeRight = removeFailures(root.right)
# Check if successfully removed children
if removeLeft:
root.left = None
if removeRight:
root.right = None
if root.data == 0 and removeLeft and removeRight:
root = None
return True
return False
输出:
4
1
0
3
5
0
0
0
3
4
6
*************************
4
1
0
3
5
3
4
6
将节点本身设置为None
是不够的,因为父节点仍保留对其的引用。因此,需要将对该节点的所有引用都设置为None
才能正确删除它。