【问题标题】:How to convert a list of edges to a tree in python?如何在python中将边列表转换为树?
【发布时间】:2022-07-27 00:55:51
【问题描述】:

我有一个边缘列表,格式如下:

edges=[[1,4],[1,3],[1,2],[3,5],[3,6],[3,7]]

在每条边中,第一个元素是父节点,第二个是子节点,即在

[1,4]---->(1为父节点,4为子节点)

我必须创建一个函数来返回指向树根的指针。起初我尝试创建字典,但创建后我无法继续。

请提供有关如何实现此功能的任何想法?

【问题讨论】:

  • 添加您想出的任何方法
  • " 指向根的指针":Python 没有指针,只有对象。
  • "pointer to the root of the tree" --> 如果一个图是图论定义中的树,那么 any 节点可以用作在术语的数据结构意义上将该图​​转换为树的根。
  • 糟糕,忽略我之前的评论。您拥有的不是(无向)图,而是有向图。在有向图的情况下,我们有时喜欢说“弧”而不是“边”,以明确表示它们是有向的。

标签: python algorithm graph tree binary-tree


【解决方案1】:

创建树形数据结构的方法有很多……而且 Python 没有指针数据类型,所以树的根是对象。

这是一种方法:

首先定义一个Node类:

class Node():
    def __init__(self, data=None):
        self.data = data
        self.children = []

然后是主算法:

def create_tree(edges):
    # Get all the unique keys into a set
    node_keys = set(key for keys in edges for key in keys)
    # Create a Node instance for each of them, keyed by their key in a dict:
    nodes = { key: Node(key) for key in node_keys }
    # Populate the children attributes from the edges
    for parent, child in edges:
        nodes[parent].children.append(nodes[child])
        # Remove the child from the set, so we will be left over with the root
        node_keys.remove(child)
    # Get the root from the set, which at this point should only have one member
    for root_key in node_keys:  # Just need one
        return nodes[root_key]

运行如下:

# Example run
edges = [[1,4],[1,3],[1,2],[3,5],[3,6],[3,7]]
root = create_tree(edges)

如果您想快速验证树的形状,请将此方法添加到Node 类中:

    def __repr__(self, indent=""):
        return (indent + repr(self.data) + "\n"
                + "".join(child.__repr__(indent+"  ") 
                          for child in self.children))

并用它来打印树:

print(root)

print 方法只是可视化树的一种非常简单的方法。再多一点代码,你也可以画出树的分支,但这足以调试代码了。

【讨论】:

  • print() 应替换为 __repr__imo
  • @AbhinavMathur,是的,已转换。
【解决方案2】:

假设它总是一棵树(因此我们没有两个单独的图),任务是确定哪个数字永远不会出现在第二个位置。

所以:

  1. 获取我们称之为possible_roots的所有数字(节点)的列表
  2. 迭代你的边缘列表并从我们上面的列表中删除子节点possible_roots
  3. 如果是树,possible_roots 中必须只剩下一个元素。这是你树的根。

【讨论】:

    【解决方案3】:

    你需要找出哪个顶点没有父节点。这可以通过构建所有顶点的set,然后丢弃具有父顶点的顶点来完成。

    或者,这可以通过一方面构建所有父顶点的集合,另一方面构建所有子顶点的集合来完成;然后采取不同的parents - children

    那么有三种可能:

    • 没有剩余顶点。这意味着您的有向图包含一个循环,并且没有根。示例:[[0,1], [1,2], [2,0]]
    • 还剩下一个以上的顶点。这意味着您的有向图包含多个“根”。示例:[[0,2], [1,2]]
    • 只剩下一个顶点。这必须是根。
    # FIRST METHOD
    def get_root(dag):
        candidates = set(parent for (parent,_) in dag)
        for _,child in dag:
            candidates.discard(child)
        assert(len(candidates) == 1) # or handle len(candidates) == 0 and len(candidates) > 1 with an if/elif/else
        return candidates.pop()
    
    # SECOND METHOD
    def get_root(dag):
        parents, children = map(frozenset, zip(*dag))
        candidates = parents - children
        root, = candidates  # will raise exception if len(candidates) != 1
        return root
    

    测试:

    print( get_root([[1,4],[1,3],[1,2],[3,5],[3,6],[3,7]]) )
    # 1
    
    print( get_root([[0,2], [1,2]]) )
    # ValueError: too many values to unpack (expected 1)
    
    print( get_root([[0,1], [1,2], [2,0]]) )
    # ValueError: not enough values to unpack (expected 1, got 0)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-22
      • 1970-01-01
      • 2023-03-29
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      • 1970-01-01
      相关资源
      最近更新 更多