需要类似于DFS的图算法

发布于 2024-08-22 07:10:12 字数 376 浏览 7 评论 0原文

我很好奇是否有一种特定的图算法可以通过选择起始节点然后通过 DFS 继续来遍历未加权的非循环有向图。如果遇到具有未搜索前驱的节点,则它应该回溯传入路径,直到探索了所有要开始的路径。

我找到了图算法的维基百科类别,但是这里有一小部分算法,我对他们中的大多数人都不熟悉。

编辑:示例: 给定图 {AB, EB, BC, BD},遍历为:{A,B,E,B,C,D} 或唯一顺序为 {A,B,E,C,D}。 请注意,与 BFS 或 DFS 不同,如果第一个起始节点的所有路径都已耗尽,则该算法不需要在新的起始节点处重新开始。

I'm curious if there is a specific graph algorithm that traverses an unweighted acyclic directed graph by choosing a start node and then proceeding via DFS. If a node is encountered that has unsearched predecessors then it should back track the incoming paths until all paths to start have been explored.

I found a wikipedia category for graph algorithms but there is a small sea of algorithms here and I'm not familiar with most of them.

EDIT: example:
given the graph {AB, EB, BC, BD}, traverse as: {A,B,E,B,C,D} or unique order as {A,B,E,C,D}.
Note this algorithm unlike BFS or DFS does not need to begin again at a new start node if all paths of the first start node are exhausted.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏至、离别 2024-08-29 07:10:12

在DFS中,通常根据从u开始的边来选择u之后要访问的顶点。您首先要根据以 u 结尾的边进行选择。为此,您可以拥有 转置图 信息,并尝试从那里获取顶点第一的。

它会是这样的:

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)

In DFS, you usually choose the vertex to be visited after u based on the edges starting at u. You want to choose based first on the edges ending at u. To do this, you could have a transpose graph info, and try to get the vertex from there first.

It would be something like this:

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)
沒落の蓅哖 2024-08-29 07:10:12

您正在寻找的是拓扑排序。据我所知,没有任何简单的方法可以在不进行任何预先计算的情况下按拓扑排序顺序遍历图。

获得顶排序的标准方法是进行标准的 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 的元素即可纠正该问题。

What you are looking for is the topological sort. As far as I'm aware there's no easy way to traverse a graph in its topologically sorted order without any precomputation.

The standard way to get the topsort is to do a standard DFS, and then store the visited nodes in order of their visiting times. Finally, reverse those nodes and voila, you have them in the order you desire.

Pseudocode:

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

The list topsort will then contain the vertices in the reverse order that you want. Just reverse the elements of topsort to correct that.

百思不得你姐 2024-08-29 07:10:12

如果您正在寻找拓扑排序,您也可以这样做,给定一个邻接列表(或边列表(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 )

给定一个邻接列表 (或边列表 (u,v)),这是 O( V + E ),因为每个边都被触摸两次 - 一次递增,一次递减,每次需要 O(1) 时间。对于普通队列,每个顶点最多也会被队列处理两次 - 这也可以通过标准队列在 O(1) 中完成。

请注意,这与 DFS(至少是直接实现)不同,因为它处理森林。

另一个有趣的注意事项是,如果您用强加某种结构/排序的 priority_queue 替换 queue,您实际上可以返回按某种顺序排序的结果。

例如,对于规范的类依赖图(如果您选择了 Y 类,则只能选择 X 类):

100:
101: 100
200: 100 101
201: 
202: 201

您可能会得到以下结果:

100, 201, 101, 202, 200

但如果您更改它,以便您始终希望首先选择编号较低的类,那么您可以轻松地将其更改为返回:

100, 101, 200, 201, 202

If you're looking for topological sort, you can also do this, given an adjacency list (or a list of edges (u,v) which you can preprocess in O(E) time):

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 )

Given an adjacency list (or a list of edges (u,v)), this is O( V + E ), since each edge is touched twice - once to increment, once to decrement, in O(1) time each. With a normal queue, each vertice will also be processed by the queue at most twice - which can be done also in O(1) with a standard queue.

Note that this differs from the DFS (at least a straight-up implementation) in that it handles forests.

Another interesting note is that if you substitute queue with a priority_queue imposing some sort of structure/ordering, you can actually return the results sorted in some order.

For example, for a canonical class dependency graph (you can only take class X if you took class Y):

100:
101: 100
200: 100 101
201: 
202: 201

you would probably get, as a result:

100, 201, 101, 202, 200

but if you change it so that you always want to take lower numbered classes first, you can easily change it to return:

100, 101, 200, 201, 202
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文