在2元组python列表中循环检测

时间:2014-04-01 12:57:48

标签: python algorithm python-2.7

给定2元组(源,目标)中的边缘列表,是否有任何有效的方法来确定是否存在循环?例如,在下面的示例中,存在循环,因为1 - > 3 - > 6 - > 4 - > 1.一个想法是计算列表中每个整数的出现次数(同样,有没有有效的方法来做到这一点?)。有没有更好的方法?我发现10,000个2元组边缘信息存在问题。

a = [(1,3), (4,6), (3,6), (1,4)]

1 个答案:

答案 0 :(得分:1)

我假设你想在你的边缘列表所代表的无向图中找到一个循环而你不想计算"琐碎的"大小为1或2的循环。

你仍然可以使用标准的depth-first search,但你需要对节点着色(一个简单的标志,表明你已访问过哪些节点是不够的)有点小心了:

from collections import defaultdict

edges = [(1,3), (4,6), (3,6), (1,4)]
adj = defaultdict(set)
for x, y in edges:
    adj[x].add(y)
    adj[y].add(x)

col = defaultdict(int)
def dfs(x, parent=None):
    if col[x] == 1: return True
    if col[x] == 2: return False
    col[x] = 1
    res = False
    for y in adj[x]:
        if y == parent: continue
        if dfs(y, x): res = True
    col[x] = 2
    return res

for x in adj:
    if dfs(x):
        print "There's a cycle reachable from %d!" % x

这将检测深度优先森林中是否存在后边缘,该森林跨越至少2个级别。如果存在一个简单的大小周期> = 2就是这种情况。通过存储父指针,如果找到它,您也可以实际打印周期。

对于大型图形,您可能希望使用显式堆栈而不是递归,如illustrated on Wikipedia