【问题标题】:Preorder tree walk of a minimum spanning tree generated by Prim's algorithmPrim算法生成的最小生成树的前序树遍历
【发布时间】:2017-09-20 11:47:52
【问题描述】:

我正在尝试实现一种近似算法来解决旅行商问题 (TSP),当三角形不等式适用于边权重时,可以使用该算法。如 Cormen et al., Introduction to Algorithms (3rd 3d.) 中所述,伪代码为:

这是一个例子:

我正在苦苦挣扎的是如何在 Prim 算法生成的树上实现预排序树遍历。由于这不是二叉搜索树,https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2 给出的伪代码似乎不适用。

相反,节点不具有leftright 属性,而是具有keyparent 属性。以下是我在 Prim 算法的实现中生成它们的方式(带有一个小测试用例):

import math
import copy
import pytest
import pandas as pd
from cached_property import cached_property


class Node(object):
    def __init__(self, key=math.inf, parent=None):
        self.key = key
        self.parent = parent

    def __lt__(self, other):
        return self.key < other.key


class Graph(object):
    def __init__(self, edges):
        self.edges = edges

    @cached_property
    def nodes(self):
        _nodes = set()
        for edge in self.edges:
            _nodes.add(edge[0])
            _nodes.add(edge[1])
        return {node: Node() for node in list(_nodes)}

    @cached_property
    def adj(self):
        A = {node: [] for node in self.nodes}
        for edge in self.edges:
            u, v, _ = edge
            A[u].append(v)
            A[v].append(u)
        return A

    @cached_property
    def w(self):
        N = len(self.nodes)
        none_array = [[None for _ in range(N)] for _ in range(N)]
        df = pd.DataFrame(none_array, index=sorted(self.nodes), columns=sorted(self.nodes))
        for edge in self.edges:
            u, v, weight = edge
            df.set_value(u, v, weight)
            df.set_value(v, u, weight)
        return df

    def mst_prim(self, root):
        r = self.nodes[root]
        r.key = 0
        Q = copy.copy(self.nodes)
        while Q:
            u = min(Q, key=Q.get)
            u_node = Q.pop(u)
            for v in self.adj[u]:
                if v in Q and self.w[u][v] < self.nodes[v].key:
                    self.nodes[v].parent = u
                    self.nodes[v].key = self.w[u][v]


@pytest.fixture
def edges_simple():
    return [('a', 'b', 4),
            ('a', 'h', 8),
            ('b', 'h', 11),
            ('h', 'i', 7),
            ('b', 'c', 8),
            ('h', 'g', 1),
            ('i', 'c', 2),
            ('i', 'g', 6),
            ('c', 'd', 7),
            ('g', 'f', 2),
            ('c', 'f', 4),
            ('d', 'f', 14),
            ('d', 'e', 9),
            ('f', 'e', 10)
            ]

def test_mst_prim(edges_simple):
    graph = Graph(edges_simple)
    graph.mst_prim(root='a')
    # print("\n")
    # for u, node in graph.nodes.items():
    #   print(u, node.__dict__)
    assert graph.nodes['a'].parent is None
    assert graph.nodes['i'].parent == 'c'
    assert graph.nodes['d'].parent == 'c'



if __name__ == "__main__":
    # pytest.main([__file__+"::test_mst_prim", "-s"])
    pytest.main([__file__, "-s"])

如何在此图上执行预序树遍历? (请注意,这个问题类似于pre-order traversal of a Minimum spanning tree,但我发现那里给出的答案相当高级)。

【问题讨论】:

    标签: python algorithm tree preorder


    【解决方案1】:

    我建议您在 Node 类中添加一个新列表,例如名为 children

    在您的Prim's 算法之后,您可以运行您获得的节点并将它们添加到其父级的children。复杂度是O(n),所以没什么大不了的。之后DFS 的遍历就很容易了。

    但同样,正如您提到的post,您必须为您的孩子选择一个订单以进行preorder 遍历。在你的情况下,当你只引用你的 parent 时,没有办法知道 left-most 孩子是什么。

    【讨论】:

      【解决方案2】:

      我有点困惑,为什么 Cormen 书中的算法提到了前序遍历,因为在最小生成树 MST 中节点的“孩子”之间没有顺序。

      据我了解,您只需在 MST 上执行深度优先搜索 (DFS),如 herehere 所述。这意味着如果在节点 u 上,您访问它的其中一个邻居或“孩子”,没有特定的顺序。

      您可以通过使用在您的类中表示为adj 的图形的邻接表表示来实现 DFS。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-16
        • 1970-01-01
        • 1970-01-01
        • 2010-12-18
        • 1970-01-01
        相关资源
        最近更新 更多