将树表示为粘合的半边

Representing a tree as glued half-edges

我有一棵树,例如作为 networkx 对象。为了将其输入给我的黑盒算法,我需要将其保存为以下奇怪的格式:

按顺时针顺序遍历树。当我穿过边缘的一侧时,我会逐渐标记它。然后我想为每条边保存其两侧的标签。

例如,星形将成为列表 [(0,1),(2,3),(4,5),...],具有 3 个顶点的路径将成为 [(0,3),(1,2)]

我很难实现这个。如何才能做到这一点?我可以使用任何库。

我在 networkx 中发现了这个很棒的内置函数 dfs_labeled_edges。从那里开始变得轻而易举。

def get_new_encoding(G):
    dfs = [(v[0],v[1]) for v in nx.dfs_labeled_edges(G, source=1) if v[0]!=v[1] and v[2]!="nontree"]
    dfs_ind = sorted(range(len(dfs)), key=lambda k: dfs[k])
    new_tree_encoding = [(dfs_ind[i],dfs_ind[i+1]) for i in range(0,len(dfs_ind),2)]
    return new_tree_encoding

我会在不参考任何图书馆的情况下回答这个问题。

您需要执行深度优先遍历,并在访问子树之前以及在之后记录(全局)增量数30=] 你访问过它。这两个数字构成了你必须前置到你从子树遍历得到的结果的元组。

这里是一个需要将图表示为邻接表的实现。 main函数需要获取根节点和邻接表

def iter_naturals(): # helper function to produce sequential numbers
    n = 0
    while True:
        yield n
        n += 1

def half_edges(root, adj):
    visited = set()
    sequence = iter_naturals()

    def dfs(node):
        result = []
        visited.add(node)
        for child in adj[node]:
            if child not in visited:
                forward = next(sequence)
                path = dfs(child)
                backward = next(sequence)
                result.extend([(forward, backward)] + path)
        return result

    return dfs(root)

以下是您如何 运行 为您提到的两个示例。我刚刚将这些图实现为邻接列表,其中节点由它们在该列表中的索引标识:

示例 1:“星星”:

根节点是所有其他节点的父节点

adj = [
    [1,2,3], # 1,2,3 are children of 0
    [], 
    [],
    []
]
print(half_edges(0, adj))  # [(0, 1), (2, 3), (4, 5)]

示例 2:具有 3 个节点的单个路径

adj = [
    [1], # 1 is a child of 0
    [2], # 2 is a child of 1
    []
]
print(half_edges(0, adj))  # [(0, 3), (1, 2)]