查找所有BFS / DFS遍历

时间:2012-10-28 20:08:07

标签: graph traversal graph-traversal

给定一个无向循环图,我想找到所有可能的遍历,包括广度优先搜索或深度优先搜索。这是一个图表作为邻接列表:

A-BC
B-A
C-ADE
D-C
E-C

所以来自根A的所有BFS路径都是:

{ABCDE,ABCED,ACBDE,ACBED}

和DFS:

{ABCDE,ABCED,ACDEB,ACEDB}

如何以有意义的方式在算法上生成这些遍历?我想有人可以生成所有字母的排列并检查它们的有效性,但这似乎是我最后的选择。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

BFS应该非常简单:每个节点都有一定的深度。在您的示例中,您在深度1处找到A,在深度1处找到B和C,在深度2处找到E和D.在每个BFS路径中,您将使用深度为0(A)的元素作为第一个元素,然后进行任何排列深度为1(B和C)的元素,接着是深度为2(E和D)的元素的任何排列等等...... 如果查看示例,您的4个BFS路径将匹配该模式。 A始终是第一个元素,其次是BC或CB,然后是DE或ED。您可以对具有更深深度节点的图形进行概括。 要找到这一点,你需要的只是1 Dijkstra搜索,这是非常便宜的。

在DFS中,你没有很好的深度分离,这使BFS变得简单明了。我没有立即看到一个像上面那样有效的算法。您可以设置图形结构并通过遍历图形和回溯来构建路径。在某些情况下,这可能不是非常有效,但它可能足以满足您的应用。

答案 1 :(得分:0)

除了您实际执行所有可能的DFS和BFS遍历的明显方法之外,您可以尝试这种方法:

第1步。 在从根A开始的dfs遍历中,转换当前访问的节点的邻接列表,如下所示:首先从列表中删除节点的父节点。其次,生成adj列表中剩余节点的所有排列。

因此,如果您来自节点A的节点C,您将执行以下操作:

C -> ADE transform into C -> DE transform into C -> [DE, ED]

第2步。 在步骤1之后,您将获得以下转换后的调整列表:

A -> [CB, BC]
B -> []
C -> [DE, ED]
D -> []
E -> []

现在启动从(A,0)开始的处理,其中对中的第一项是遍历路径,第二项是索引。让我们假设我们有两个队列。 BFS队列和DFS队列。我们将这对配对成两个队列。

现在我们重复以下操作,首先是一个队列,直到它为空,然后是另一个队列。

我们从队列中弹出第一对。我们得到(A,0)。节点A映射到[BC,CB]。所以我们生成两个新路径(ACB,1)和(ABC,1)。将这些新路径放入队列中。

从队列中取出第一个得到(ACB,1)。索引为1,因此我们查看路径字符串中的第二个字符。这是C.节点C映射到[DE,ED]。

  • 此路径的BFS孩子将是(ACBDE,2)和(ACBED,2),我们通过追加孩子排列获得。
  • 此路径的DFS子级将是(ACDEB,2)和(ACEDB,2),我们通过之后的子排列插入获得到路径字符串中。

我们根据我们正在处理的队列生成新路径,并根据上述内容将它们放入队列中。因此,如果我们正在处理BFS队列,我们​​放入(ACBDE,2)和(ACBED,2)。我们队列的内容现在是:(ABC,1),(ACBDE,2),(ACBED,2)。

我们从队列中弹出(ABC,1)。生成(ABC,2),因为B没有孩子。并得到队列: (ACBDE,2),(ACBED,2),(ABC,2)等。在某些时候,我们最终会得到一堆索引不包含在路径中的对。例如,如果我们得到(ACBED,5),我们就知道这是一条完成的路径。