我很好奇是否有特定的图算法通过选择一个起始节点然后通过DFS进行遍历未加权的非循环有向图。如果遇到具有未搜索的前驱的节点,那么它应该回溯跟踪传入的路径,直到探索了所有要启动的路径。
我找到了wikipedia category for graph algorithms,但这里有一小部分算法,我对大多数算法并不熟悉。
编辑:示例: 给定图{AB,EB,BC,BD},遍历为:{A,B,E,B,C,D}或唯一顺序为{A,B,E,C,D}。 请注意,如果第一个起始节点的所有路径都耗尽,则此算法与BFS或DFS不同,不需要在新的起始节点重新开始。
答案 0 :(得分:2)
您正在寻找的是拓扑类型。据我所知,没有任何简单的方法可以在没有任何预计算的情况下以拓扑排序的顺序遍历图形。
获得topsort的标准方法是执行标准DFS,然后按访问时间顺序存储受访节点。最后,反转那些节点,瞧,你按照你想要的顺序。
伪代码:
list topsort
procedure dfs(vertex u)
mark u as visited
for each edge (u, v)
if v not visited
dfs(v)
add u to the back of topsort
列表topsort
将按照您想要的相反顺序包含顶点。只需反转topsort的元素即可纠正。
答案 1 :(得分:2)
在DFS中,您通常根据从u开始的边选择要访问的顶点。您希望首先选择基于结束于u的边缘。为此,您可以获得transpose graph信息,并尝试首先从那里获取顶点。
这将是这样的:
procedure dfs(vertex u)
mark u as visited
for each edge (v, u) //found in transpose graph
if v not visited
dfs(v)
for each edge (u, w)
if v not visited
dfs(w)
答案 2 :(得分:2)
如果您正在寻找topological sort
,您也可以执行此操作,给定adjacency list(或您可以在(u,v)
时间预处理的边O(E)
列表):
list top_sort( graph in adjacency list )
parent = new list
queue = new queue
for each u in nodes
parent(u) = number of parents
if ( parent(u) is 0 ) // nothing points to node i
queue.enqueue( u )
while ( queue is not empty )
u = queue.pop
add u to visited
for each edge ( u, v )
decrement parent(v) // children all have one less parent
if ( parent(v) is 0 )
queue.enqueue( v )
给定adjacency list
(或边(u,v)
列表),这是O( V + E )
,因为每个边被触摸两次 - 一次递增,一次递减,在{{1每个时间。使用普通队列时,队列最多也会处理每个顶点两次 - 这也可以在O(1)
中使用标准队列完成。
请注意,这与DFS(至少是直接实现)的不同之处在于它处理森林。
另一个有趣的注意事项是,如果用O(1)
替换queue
强加某种结构/排序,你实际上可以按某种顺序返回结果。
例如,对于规范类依赖图(如果你使用Y类,你只能使用X类):
priority_queue
你可能会得到,结果:
100:
101: 100
200: 100 101
201:
202: 201
但是如果你改变它以便你总是想首先采用编号较低的类,你可以很容易地改变它以返回:
100, 201, 101, 202, 200