当前位置: 首页 > 知识库问答 >
问题:

图-如何避免在深度优先搜索中重复处理相同的边两次?

秦俊发
2023-03-14

算法设计手册对BFS和DFS的描述相当到位。书中关于dfs的代码在决定是否避免双处理边时有一个问题。我找到了勘误表并将勘误表应用到代码中,但我仍然认为精炼后的代码有一个检查双重处理边的问题。

dfs(graph *g, int v) {
       edgenode *p;
       int y;
       if (finished) return;
       discovered[v] = TRUE;
       time = time + 1;
       entry_time[v] = time;
       process_vertex_early(v);
       p = g->edges[v];
       while (p != NULL) {
             /* temporary pointer */
             /* successor vertex */
             /* allow for search termination */
             y = p->y;
             if (discovered[y] == FALSE) {
                   parent[y] = v;
                   process_edge(v,y);
                   dfs(g,y);
             }
             else if (**(!processed[y] && parent[v] != y)** || (g->directed))
                   process_edge(v,y);
             if (finished) return;
             p = p->next;
       }
       process_vertex_late(v);
       time = time + 1;
       exit_time[v] = time;
       processed[v] = TRUE;
}

所以有问题的地方是条件之一。让我们假设它是无向图,所以我们可以只忽略(G->directed)的条件。

好的,让我们首先关注parent[v]!=y。如果parent[v]==y,当然,我们不需要再次处理边V->y,因为在处理顶点y时,y->v已经处理过一次了。

如果parent[v]!=y,我的问题是!processed[y]&是否必要。

因此,如果我们永远不会肉处理顶点,我们可以删除!processed[y],因为它永远是真的。

共有1个答案

赵智
2023-03-14

否,processed[y]==true可能产生true。

看下面的图,并假设如下[可行]DFS遍历

v0,v1,v2

v0启动,然后在处理(v0,v1)后递归调用DFS(v1)。现在,v1处理(v1,v2)并递归调用DFS(v2)v2看到发现了v0并转到else if语句,看到未处理(v0,v2)并且父[v2]!=v0[v2是通过v1]发现的。

现在,当我们从递归返回到v0时,当我们检查下一个“子”时,它是v2v2已被发现,因此我们转到else if,而v2不是v0的父级,因此如果没有!processed[y]部分,我们将对(v0,v2)进行两次处理。

唯一阻止这种情况发生的是处理了[y]==true

 类似资料:
  • 我有一个无向连通图。我使用邻接矩阵实现了它,它是一个2维数组。 据我所知,DFS在兄弟节点之前访问子节点。BFS先于孩子探望兄弟姐妹。 这两个我是这样实现的: 如果让我执行一个从D到E的DFS,是D、C、a、E还是D、E。我以为DFS和BFS必须访问每个节点,在这种情况下B不能访问。我不知道我应该如何改变我目前的方法来满足这些要求。

  • 主要内容:深度优先搜索(简称“深搜”或DFS),广度优先搜索,总结前边介绍了有关图的 4 种存储方式,本节介绍如何对存储的图中的顶点进行遍历。常用的遍历方式有两种: 深度优先搜索和 广度优先搜索。 深度优先搜索(简称“深搜”或DFS) 图 1 无向图 深度优先搜索的过程类似于树的先序遍历,首先从例子中体会深度优先搜索。例如图 1 是一个无向图,采用深度优先算法遍历这个图的过程为: 首先任意找一个未被遍历过的顶点,例如从 V1 开始,由于 V1 率先访问过了,所以

  • 本文向大家介绍深度优先搜索,包括了深度优先搜索的使用技巧和注意事项,需要的朋友参考一下 图遍历是按某种系统顺序访问图的所有顶点的问题。遍历图主要有两种方法。 广度优先搜索 深度优先搜索 深度优先搜索(DFS)算法从顶点v开始,然后遍历到之前未访问过的相邻顶点(例如x),并将其标记为“已访问”,然后继续处理x的相邻顶点,依此类推。 如果在任何一个顶点上遇到所有相邻顶点都被访问过,则它将回溯直到找到具

  • 3. 深度优先搜索 现在我们用堆栈解决一个有意思的问题,定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线

  • 我已经查看了其他各种StackOverflow答案,它们都与我的讲师在幻灯片中写的不同。 深度优先搜索的时间复杂度为O(b^m),其中b是搜索树的最大分支因子,m是状态空间的最大深度。如果m比d大得多,这很糟糕,但如果搜索树“浓密”,则可能比广度优先搜索快得多。 他接着说。。 空间复杂度为O(bm),即动作序列长度的空间线性!只需要存储从根到叶节点的单个路径,以及路径上每个节点的剩余未扩展兄弟节点

  • 我必须为一个算法开发伪代码,该算法计算给定顶点V和边E的图G=(V,E)中连通分量的数量。 我知道我可以使用深度优先搜索或广度优先搜索来计算连接组件的数量。 但是,我想用最高效的算法来解决这个问题,但是我不确定每个算法的复杂度。 下面是一个用伪代码形式写DFS的尝试。 下面尝试以伪代码形式编写 BFS。 我的讲师说BFS与DFS具有相同的复杂性。 然而,当我搜索深度优先搜索的复杂度时,它是O(V^