【问题标题】:Representing tree of nodes as lists将节点树表示为列表
【发布时间】:2018-06-12 08:23:07
【问题描述】:

我有两组数据 A 和 B,A 是起始节点,B 是结束节点。在每个集合中都有节点的编号、该节点的 X 坐标和 Y 坐标,如下所示。读取表时节点 0 连接到节点 1,节点 1 连接到节点 2,节点 0 也连接到节点 3,依此类推。

  A          X_A           Y_A             B            X_B            Y_B
 --------------------------------------------------------------------------
 0           x_0           y_0             1            x_1            y_1
 1           x_1           y_1             2            x_2            y_2
 0           x_0           y_0             3            x_3            y_3
 2           x_2           y_2             4            x_4            y_4
 0           x_0           y_0             5            x_5            y_5
 3           x_3           y_3             6            x_6            y_6
 1           x_1           y_1             7            x_7            y_7

每个列表都是一个数组,所以总共有六个数组。

我想提取数据,以便可以通过坐标读取每段线。一段线由一组节点定义,这些节点的起点和终点要么是交叉节点,要么是结束节点:交叉节点连接到两个以上的其他节点,而结束节点只连接到另一个节点。

在这个例子中,最终结果应该是:

[(x_0, y_0),(x_5, y5)]
[(x_0, y_0),(x_3, y_3),(x_6, y_6)]
[(x_0, y_0),(x_1, y_1)]
[(x_1, y_1),(x_7, y_7)]
[(x_1, y_1),(x_2, y_2),(x_4, y_4)]

我对如何用 python 做到这一点感到很困惑,感谢任何帮助!

【问题讨论】:

  • 因此,如果您将其视为graph,您正在搜索所有叶子的方法列表。
  • 是的,但是如何在 python 中做到这一点?
  • 为什么最终结果是:[(x_0, y_0),(x_5, y5)][(x_0, y_0),(x_3, y_3),(x_6, y_6)][(x_0, y_0),(x_1, y_1)][(x_1, y_1),(x_7, y_7)][(x_1, y_1),(x_2, y_2),(x_4, y_4)]而不是:[(x_0, y_0),(x_5, y5)][(x_0, y_0),(x_3, y_3),(x_6, y_6)][(x_0, y_0),(x_1, y_1),(x_7, y_7)]pan [(x_0, y_0),(x_1, y_1),(x_2, y_2),(x_4, y_4)]
  • 我建议您将图形表示为Adjacency List,然后编写递归代码来打印列表。
  • 因为1是一个与其他三个节点相连的交集节点

标签: python arrays python-3.x list


【解决方案1】:

似乎一个简单的 DFS 就可以解决问题。我将中间节点定义为那些 他们正好有两个邻居。你定义了两个规则:

  • 我们不能从中间节点开始,也不能从中间节点停止。
  • 每个段至少有两个节点(隐式)。

代码:

class SegmentFinder():
    def __init__(self, A, B):
        # create the adjacency lists
        self.__d = {}
        self.__reverse_d = {}
        for a,b in zip(A,B):
            self.__d.setdefault(a, []).append(b)
            self.__reverse_d.setdefault(b, []).append(a)

    def find(self):
        for n in self.__d:
            if not self.__is_middle_node(n): # we can't start with a middle node
                yield from self.__dfs([n])

    def __dfs(self, segment):
        # We don't need to store the visited nodes, since we start with a non middle
        # node. If it has 1 neighbour, we won't be back. If it has more than 2,
        # then it will end the search.
        n = segment[-1]
        if len(segment) == 1 or self.__is_middle_node(n): # we can't stop with a middle node
            for n2 in self.__d[n]:
                yield from self.__dfs(segment + [n2])
        else: # a segment has at least two nodes
            yield segment

    def __is_middle_node(self, n):
        """Exactly two neighbours"""
        return len(self.__d.get(n, [])) == 1 and len(self.__reverse_d.get(n, [])) == 1

s = SegmentFinder(A, B)
list(s.find())
# [[1, 2, 4], [1, 7], [0, 3, 6], [0, 1], [0, 5]]

要添加坐标,只需将路径中的节点与它们的 x,y 映射。对于任何图算法,通常只在节点id 上工作并在之后添加“装饰”会更容易:

coords = dict(zip(A+B, zip(xa+xb,ya+yb)))
[coords[n] for path in s.find() for n in path]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2018-06-30
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多