簡體   English   中英

Python 中的引用問題(樹)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM