[英]Trouble with references in Python (trees)
我正在嘗試刪除所有只包含零的子樹。 我的代碼如下。 現在,在根節點上運行 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
要檢查樹中的所有節點是否都包含零,您必須遍歷這些節點中的每一個。 一種可能性是創建一個__iter__
方法來查找樹中的所有節點,然后可以應用any
內置函數來確定它們是否都等於 0。 最后,一個簡單的遞歸方法可以檢查左右孩子並在必要時刪除。
為了創建樹的簡單性, kwargs
被用於在不實現旋轉方法或一長串賦值語句的情況下就地構建結構:
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
提供了額外的檢查。
在子節點上遞歸調用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
才能正確刪除它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.