我想在图中找到两个节点之间的所有路径。我写了一个递归函数,借助深度优先搜索算法找到所有路径。但对于较大的图形,效率非常低,因此我不能将它用于我的程序。
我正在考虑为我的问题实施迭代方法。这对我来说非常耗时。所以有人知道这是否有意义?
在这种情况下迭代方式是否更有效?或者是否可以优化我的递归方法?
我目前的职能:
function RecDFS(g::GenericGraph, visited)
nodes = out_neighbors(visited[length(visited)], g)
for i in nodes
if in(i,visited)
continue
end
if i.label == "End"
push!(visited,i)
println(visited) # print every path from the first node in visited to the node with the label End
pop!(visited)
break
end
# continue recursive..
for i in nodes
if (in(i, visited) || i.label == "End")
continue
end
push!(visited,i)
depthFirstSearchAllI(g, visited)
pop!(visited)
end
end
答案 0 :(得分:3)
你试图解决的问题实际上是NP难问题,这意味着它还没有多项式时间算法!
所以你可以为你的问题找到一些优化,但你不能让它运行得足够快!
与优化一样,您可以执行以下操作。首先,您在问题主题中提到您的输入是DAG图,而DAG根据定义具有以下属性:
DAG的两个不同连接部分中的两个节点之间没有路径。
所以,如果你有一个DAG连接部分中的节点列表(这在多项式时间内是可以实现的),你可以很容易地划掉很多无望的组合。
在使程序迭代时,您可以轻松地使用堆栈。只需用stack.push(节点)替换每个递归调用,并将代码的遍历部分放在一段时间内(堆栈不为空),然后逐个弹出节点,除非没有。应该这样做。
答案 1 :(得分:2)
经过一些想法,我找到了解决问题的好方法。看看这个示例代码:
function RecDFS(g::GenericGraph, visited)
nodes = out_neighbors(visited[length(visited)], g)
if(checkPath(visited))
for i in nodes
if in(i,visited)
continue
end
if i.label == "End"
push!(visited,i)
println(visited) # print every path from the first node in visited to the node with the label End
pop!(visited)
break
end
end
# continue recursive..
for i in nodes
if (in(i, visited) || i.label == "End")
continue
end
push!(visited,i)
depthFirstSearchAllI(g, visited)
pop!(visited)
end
end
end
总而言之,我刚刚添加了一个if语句。如果路径到目前为止有效,则函数checkPath(visited)
返回true。如果路径(或路径段)无效,则函数结束。
对于我的具体问题,这是一个非常好的解决方案。它在我的测试运行中快了100倍,对于我的500个节点和16000个边缘的最大问题实例只需要15秒。
非常感谢Ashkan Kzme和Rob的帮助。
答案 2 :(得分:1)
在DAG中执行topological sort个顶点,以获得<Connector port="listeningport" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />
。假设您的起始节点为[v0, v1, ... , vn]
,即您的目的地vs
。 (如果vt
则没有路径)
然后,对于s > t
中的每个i
,计算从s+1 .. t
到P(i)
的路径vs
,如下所示:
vi
,那就是一条路径(长度为1)vs -> vi
,j
并且边缘为s < j < i
。添加从vj -> vi
获取路径并附加边P(j)
vj -> vi
,无法保证从i
到vs
正如已经评论过的那样,可能存在指数级的路径,因此输出所有路径通常不能在低于指数的时间内完成。但是,您可以使用此方法计算线性时间内的路径数。
答案 3 :(得分:0)
您可以使用队列进行深度优先搜索,从而保存您刚刚经过的节点。