这个Python函数如何返回数字而且还有字典?

时间:2014-02-06 02:11:39

标签: python dictionary graph

下面是算法类的分配,我们正在学习节点,路径等。代码用于检查一个节点是否可以从另一个节点访问。下面的代码有效,但我不明白为什么。 G是包含每个节点作为键的“图形”,其值为=它连接的节点。下面的mark_component函数返回给定节点的多个节点。

但是在函数check_connection中,如果两个节点可以访问,它将返回True,它会调用此mark_component函数,然后测试节点是否在字典中。

我没有得到的是check_connection以空字典“标记”开始,然后使用此字典调用mark_component。然后将节点添加到其中。但是mark_component返回一个数字,那么check_connection函数如何能够“读取”标记的内容?就该功能而言,我认为标记仍然是空的。我想我认为标记是一个包含字典的局部变量,但它显然可以传递给另一个函数并进行更改。

有人可以向我解释一下吗?非常感谢

def mark_component(G, node, marked):
    marked[node] = True
    total_marked = 1
    for neighbor in G[node]:
        if neighbor not in marked:
            total_marked += mark_component(G, neighbor, marked)
    return total_marked

def check_connection(G, v1, v2):
    # Return True if v1 is connected to v2 in G
    # or False if otherwise
    marked = {}
    mark_component(G, v1, marked)
    return 'a' in marked       


G = {'a': {'d': 1, 'g': 1}, 'c': {'g': 1}, 'b': {'f': 1},
     'e': {'h': 1, 'f': 1}, 'd': {'a': 1, 'g': 1},
     'g': {'a': 1, 'c': 1, 'd': 1}, 'f': {'b': 1, 'e': 1}, 'h': {'e': 1}}



print check_connection(G,'a', 'b') 

3 个答案:

答案 0 :(得分:2)

是的,marked本身是一个可变数据结构,这意味着它的内容甚至可以在其原始范围之外进行更改。当marked传递给mark_component函数时,后者会收到对marked对象的引用,并且能够通过使用索引器访问该引用来更新其内容(即{{{ 1}})。

然而,函数marked[node]仍然存储在变量check_connection中的内存中的marked对象。执行表达式marked时,'a' in marked引用marked函数更新的对象。

这个概念类似于C和C ++等其他语言中的指针概念(又名mark_component)。

答案 1 :(得分:0)

我猜这个算法没有很好地实现。

这是有向图中的贪婪搜索。我从第一个节点(v1)开始,尽可能地尝试。然后,它转向另一个节点。我们还在程序中标记了访问过的笔记。

嗯,它做了一些简单的优化。如果已访问该节点,请不要再次执行此操作。因此,我不会两次“检查”单个节点。

check_connection()的最后一行是错误的。我们应该检查v2是否已被访问过。因此,代码应该是

def mark_component(G, node, marked):
    marked[node] = True
    total_marked = 1
    for neighbor in G[node]:
        if neighbor not in marked:
            total_marked += mark_component(G, neighbor, marked)
    return total_marked

def check_connection(G, v1, v2):
    # Return True if v1 is connected to v2 in G
    # or False if otherwise
    marked = {}
    mark_component(G, v1, marked)
    return v2 in marked


G = {'a': {'d': 1, 'g': 1}, 'c': {'g': 1}, 'b': {'f': 1},
          'e': {'h': 1, 'f': 1}, 'd': {'a': 1, 'g': 1},
          'g': {'a': 1, 'c': 1, 'd': 1}, 'f': {'b': 1, 'e': 1}, 'h': {'e': 1}}



print check_connection(G,'a', 'b')

让我们来看看一些python的想法。 Python总是通过引用传递参数(在C ++中的vs.s.指针)。因此,调用者可以看到被调用者所做的更改。另一个是“x in b”。 “in”是在大多数python容器中实现的运算符。对于“标记”(字典),就好像v2是标记键之一。建议在python中实现这一点。

答案 2 :(得分:0)

听起来我觉得你没有认识到mark_component是递归调用的。在第一次调用mark_component之后,再次调用它以通过图形工作。正如其他人所说,这是一种经常会看到的模式。