【问题标题】:How to get leaf nodes of a tree using Python?如何使用 Python 获取树的叶节点?
【发布时间】:2014-01-08 18:55:47
【问题描述】:

您好,我是 OOP 的新手,所以在阅读本文时请记住这一点。

我有一个简单的 Python 树实现(见下面的代码)。

class TreeNode(object):
    def __init__(self, data):
        self.data = data
        self.children = []

    def add_child(self, obj):
        self.children.append(obj)

class Tree:
    def __init__(self):
        self.root = TreeNode('ROOT')

    def preorder_trav(self, node):
        if node is not None:
            print node.data
            if len(node.children) == 0:
                print "("+ node.data + ")"
                for n in node.children:
                    self.preorder_trav(n)

if __name__ == '__main__':
    tr = Tree()
    n1 = tr.root
    n2 = TreeNode("B")
    n3 = TreeNode("C")
    n4 = TreeNode("D")
    n5 = TreeNode("E")
    n6 = TreeNode("F")

    n1.add_child(n2)
    n1.add_child(n3)
    n2.add_child(n4)
    n2.add_child(n5)
    n3.add_child(n6)

    tr.preorder_trav(n1)

我现在需要的是实现一个让叶节点恢复的方法。 叶节点是指没有子节点的节点。

我想知道如何制作一个 get_leaf_nodes() 方法。

我想到的一些解决方案是

  1. __init__ 方法中创建self.leaf_nodes = []。通过这样做,我知道它只会被这个树实例看到。
  2. __init__ 方法之上创建一个类成员leaf_nodes = []。通过这样做,我知道所有树实例都将能够看到 leaf_nodes 列表。

上述解决方案将导致我在我的类中创建一个leaf_nodes 列表,以便get_leaf_nodes() 方法可以使用。我正在寻找的是只有一个get_leaf_nodes() 方法可以在我的树上进行计算并返回一个列表。

例如,在 C 语言中,我们会调用 malloc(),然后我们可以返回指向调用 get_leaf_nodes() 的函数的指针。

【问题讨论】:

  • 通常你使用递归来解决这个问题。 stackoverflow.com/questions/479343/…
  • 我知道递归。我也已经在 preorder_trav() 方法中使用了它。问题是我遇到的 OO 设计问题。我是否必须在我的类中创建一个列表,或者有一种方法可以返回叶节点列表而不在 init 中创建一个或作为类成员?

标签: python oop tree


【解决方案1】:

在python中,您可以使用内部函数来收集叶节点,然后返回它们的列表。

def get_leaf_nodes(self):
    leafs = []
    def _get_leaf_nodes( node):
        if node is not None:
            if len(node.children) == 0:
                leafs.append(node)
            for n in node.children:
                _get_leaf_nodes(n)
    _get_leaf_nodes(self.root)
    return leafs

如果您想要更干净 OOP 方法,您可以为叶子集合创建一个额外的私有方法:

def get_leaf_nodes(self):
    leafs = []
    self._collect_leaf_nodes(self.root,leafs)
    return leafs

def _collect_leaf_nodes(self, node, leafs):
    if node is not None:
        if len(node.children) == 0:
            leafs.append(node)
        for n in node.children:
            self._collect_leaf_nodes(n, leafs)

这就是我在 Java 中的做法。

【讨论】:

  • 它工作得很好。我有一些问题。 (a) 在方法中使用函数是一种干净的 OOP 方法吗? (b) 叶子 = [] 语句是保留堆还是堆栈存储空间?因为我认为如果它保留堆栈空间,叶子列表会在 get_leaf_nodes 返回后指向随机数据吗?
  • (a) 不,这不是“干净”的 OOP 方法,但是如果您不想要其中的所有功能,为什么要使用 python ;),除了从客户端的角度来看,您的对象的行为就像一个“干净”的 OOP 对象 (b)leafs = [] 创建一个 list 类型的新对象并分配一个对变量 leaf 的引用,所以当你返回它时,你只是返回一个对列表对象的引用,python一直存在直到没有引用可以到达它(python 使用垃圾收集器方法来处理 OOP)
  • 感谢您对我的问题的解释。我喜欢你的回答。我会等待更多的答案,然后我会接受它:)
【解决方案2】:

这个方法应该足以获取任何节点的叶子,如果你用树的根调用它,你将获得树的所有叶子:

def get_leaves(node):
    if not node.children:
        yield node

    for child in node.children:
        for leaf in get_leaves(child):
             yield leaf

【讨论】:

    【解决方案3】:

    寻找叶子的好递归方法之一。

    def leaf_count(self):
    
            if(self == None):
                return 0
    
            if(self.left == None or self.right == None):
                return 1
    
            return self.left.leaf_count() + self.right.leaf_count()
    

    【讨论】:

      【解决方案4】:

      我认为以前的贡献者已经正确地回答了这个问题,但没有人真正展示如何设置节点并将这些值添加到树中,然后运行它以证明它实际上可以一起工作。这就是我回答这个问题的原因:

      class Node: 
          def __init__(self, val): 
              self.val = val
              self.left = None
              self.right = None
      
      
      class Pattern():
          def getLeafs(self,root):
              if not root: 
                  return []
              if not root.left and not root.right: 
                  return [root.val]
              leaves = self.getLeafs(root.left) + self.getLeafs(root.right)
              return leaves 
      
          def similar_leaf(self, root1, root2):
              return self.getLeafs(root1) == self.getLeafs(root2)
      
      
      #simple test 
      root= Node(3)
      root.left = Node(5)
      root.right= Node(1)
      
      root.left.left =  Node(6)
      root.left.right =  Node(2)
      root.left.right.left =Node(7)
      root.left.right.right =Node(4)
      
      root.right.left =  Node(9)
      root.right.right =  Node(8)
      
      pattern =Pattern()
      print(pattern.similar_leaf(root,root))
      

      【讨论】:

        【解决方案5】:

        以下方法适用于没有左节点或右节点的子树。

        节点

        class Node:
            
            def __init__(self, data, left=None, right=None):
                self.data = data
                self.left = left
                self.right = right
        

        作为实用功能

        def get_leaf_nodes(root):
            leaves = []
            
            # If no child nodes
            if not root.left and not root.right:
                return [root.data]
            
            # If no any left child
            if not root.left:
                leaves = get_leaf_nodes(root.right)
            
            # If no any right child
            if not root.right:
                leaves = get_leaf_nodes(root.left)
            
            # If has left as well left child
            if root.left and root.right:
                leaves = get_leaf_nodes(root.left) + get_leaf_nodes(root.right)
            
            return leaves
        

        作为类方法:

        class Node:
            
            def __init__(self, data, left=None, right=None):
                self.data = data
                self.left = left
                self.right = right
        
            def get_leaf_nodes(self):
                """Get the nodes which don't have any left of right sub nodes"""
                leaves = []
              
                # If no child nodes
                if not self.left and not self.right:
                    return [self.data]
              
                # If no any left child
                if not self.left:
                    leaves = self.right.get_leaf_nodes()
              
                # If no any right child
                if not self.right:
                    leaves = self.left.get_leaf_nodes()
              
                # If has left as well left child
                if self.left and self.right:
                    leaves = self.left.get_leaf_nodes() + self.right.get_leaf_nodes()
              
                return leaves
        

        测试: 考虑二叉树:

        tree = Node(2,
                    Node(1),
                    Node(6,
                        Node(3),
                        Node(11,
                            Node(10,
                                Node(8,
                                    None,
                                    Node(9)
                                    ),
                                None
                            )
                        )
                    )
            )
        

        那么叶子是:

        # as a utility function
        l = get_leaf_nodes(tree)
        
        # or as an object
        # l = tree.get_leaf_nodes()
        print(l)
        

        [1, 3, 9]

        【讨论】:

          猜你喜欢
          • 2015-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-28
          • 2021-02-13
          • 1970-01-01
          相关资源
          最近更新 更多