Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 使用DFS的图遍历_Algorithm_Depth First Search - Fatal编程技术网

Algorithm 使用DFS的图遍历

Algorithm 使用DFS的图遍历,algorithm,depth-first-search,Algorithm,Depth First Search,我正在学习Steven S.Skiena的算法设计手册中的图形遍历。在他的书中,他提供了使用dfs遍历图的代码。下面是代码 dfs(graph *g, int v) { edgenode *p; int y; if (finished) return; discovered[v] = TRUE; time = time + 1; entry_time[v] = time; process_verte

我正在学习Steven S.Skiena的算法设计手册中的图形遍历。在他的书中,他提供了使用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]) || (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;
}
在无向图中,下面的代码似乎处理了两次边(调用方法process_edge(v,y)。一次遍历顶点v,另一次处理顶点y)
所以我添加了条件
parent[v]=y
中,如果((!processed[y])| |(g->directed))

它只处理边缘一次。然而,我不知道如何修改此代码以使用并行边和自循环边。代码应处理平行边和自循环

简短答复: 将
(!processed[y])
替换为
(!processed[y])
,而不是将其添加到条件中

详细答复: 在我看来,书中所写的实现中有一个错误,您发现并修复了这个错误(除了平行边。下面将详细介绍)。有向图和无向图的实现都应该是正确的,它们之间的区别记录在
g->directed
布尔属性中

在书中,就在实施之前,作者写道:

深度优先搜索的另一个重要特性是它将 无向图的边分为两类:树边和后边。这个 树边发现新的顶点,并且是在父关系中编码的顶点。返回 边的另一个端点是展开顶点的祖先, 于是他们指向树上

因此,假设条件
(!processed[y])
处理无向图(就像条件
(g->directed)
处理有向图一样),允许算法处理后边的边,并防止其重新处理树边(在相反方向)。但是,正如您所注意到的,当通读具有此条件的子级时,树边被视为后边,因此您应该用建议的
(父级[v]!=y)
替换此条件

只要没有平行边,算法读取无向图时,条件
(!processed[y])
始终为真(进一步详细说明为什么为真-*)。如果存在平行边-在第一次“复制”后读取的平行边将产生
false
,并且在应该处理的时候,不会处理该边。但是,您建议的条件将区分树边和其他边(后边、平行边和自循环),并允许算法仅处理那些不是相反方向的树边

要引用自边,它们在新条件和旧条件下都应该可以:它们是具有
y==v
的边。到达它们时,
y
被发现(因为
v
在通过其边缘之前被发现),未被处理(
v
仅作为最后一行处理-在通过其边缘之后),并且它不是
v
的父级(
v
不是它自己的父级)


*通过
v
的边缘,算法读取已发现的
y
的该条件(因此它不会进入第一个条件块)。如上所述(在这本书中,我将在本脚注末尾提供一个半证明),
p
是树边或后边。当发现
y
时,它不能是从
v
y
的树边。它可以是祖先的后缘,这意味着调用是在某个点开始处理此祖先的递归调用中,因此祖先的调用尚未到达最后一行,将其标记为已处理(因此仍将其标记为未处理),它可以是从
y
v
的树边,在这种情况下,相同的情况仍然存在,
y
仍被标记为未处理

每个边都是树边或后边的半证明:

为什么边不能转到兄弟节点或表亲节点而不是祖先节点? 从给定顶点v可以到达的所有节点在我们完成 从v进行遍历,因此这种拓扑对于无向图是不可能的

你说得对

引述:

(*)第171页,第2行——dfs代码有一个bug,每个树的边缘 在无向图中处理两次。这项测试需要改进 被加强为:

else if (((!processed[y]) && (parent[v]!=y)) || (g->directed))
至于循环-参见

条件
(!processed[y])
将始终为真,这也是我的结论!