我无法理解Skeina算法中的所有内容来检测图表中的周期,无论是有向还是无向
void process_edge(int v, int y) {
// if parent[v] == y it means we're visitng the same edge since this is unweighted?
// y must be discovered otherwise this is the first I'm seeing it?
if (discovered[y] && parent[v] != y) {
printf("\nfound a back edge (%d %d) \n", v, y);
}
}
void DFSRecursive(graph *g, int v) {
discovered[v] = true;
edge *e = g->edges[v];
while (e != NULL) {
int y = e->y;
if (discovered[y] == false) {
parent[y] = v;
DFSRecursive(g, y);
} else if (!processed[y] || g->directed) { // can't be processed and yet has an unvisited kid!?
process_edge(v, y, data);
}
e = e->next;
}
processed[v] = true;
}
答案 0 :(得分:3)
我对父[V]!== y的检查感到困惑,但我想在未加权的图形情况下它是有意义的,如果我们有一个只有两个节点的图形,两个节点彼此相邻,所以这个不是一个循环。我不清楚为什么它在定向案例中有意义,因为1-> 2和2-> 1被认为是一个循环,对吗?
我不同意其他答案。 cycle不会多次访问边缘,否则任何带有边缘(无定向或无定向)的图形都会有一个循环。书中给出的算法是正确的。只有在无向图时才需要检查,但在我看来,代码处理得非常干净。
如果您指的是我们可能有两个有向边的情况:
1 -> 2
2 -> 1
那么你是否认为这个循环是值得商榷的。通常,假定有向图不具有这种情况。我可以将这样的一对解释为无向边缘,然后将它走两次是没有意义的。您可以将其解释为两个有向边,然后您认为该算法是错误的。但是你的解释只会是错误的。
对于最常用的解释(也是最容易理解的),算法会按照预期的那样进行。
作为另一个例子,人们也可以允许像1 -> 1
这样的边缘。你会认为这是一个循环吗?无论哪种方式,你都不会错。这只是一个定义问题。对于教科书,人们通常使用的定义可以让作者呈现最方便(最容易理解)的解决方案。
答案 1 :(得分:1)
有向图可能。让我们假设我们有一个包含2个顶点和1个边的图:2 - > 1.如果我们从第一个顶点开始深度优先搜索,它将在我们访问第二个顶点时进行处理。所以边缘2 - > 1将导致处理的顶点。但是,对于无向图,这是不可能的。
我同意你的意见。
在我看来,这个代码的主要问题是它试图同时处理两个:有向图和无向图,这使得逻辑不清楚并且难以遵循。使用深度优先搜索检测图形中的循环实际上非常简单,因此我建议您找一个更好的实现(或自己创建,分别处理有向和无向图)。