【发布时间】:2017-05-15 02:50:18
【问题描述】:
我编写的以下 C# 算法在 O(n) 时间内检测到无向图中是否存在循环。它避免了递归,并通过字典和哈希集利用散列。但是有没有办法让我做得更好?
void Main()
{
var graph = new Dictionary<int, HashSet<int>>
{
{ 0, new HashSet<int> { 4 } },
{ 1, new HashSet<int> { 2, 3, 4 } },
{ 2, new HashSet<int> { 1 } },
{ 3, new HashSet<int> { 1, 4 } },
{ 4, new HashSet<int> { 0, 1, 3 } }
};
Console.WriteLine(HasCycle(graph, 0));
}
bool HasCycle(Dictionary<int, HashSet<int>> graph, int start)
{
var stack = new Stack<int>();
var visited = new HashSet<int>();
stack.Push(start);
var curr = start;
var prev = -1;
while (stack.Count > 0)
{
prev = curr;
curr = stack.Pop();
visited.Add(curr);
HashSet<int> neighbors;
if (graph.TryGetValue(curr, out neighbors) && neighbors != null)
{
foreach (var neighbor in neighbors)
{
if (!visited.Contains(neighbor))
{
stack.Push(neighbor);
}
else if (neighbor != prev && neighbors.Contains(prev))
{
return true;
}
}
}
}
return false;
}
【问题讨论】:
-
如果在迭代时你最终进入了一个已经访问过的节点,那么你就有一个循环。
-
但是对于一个无向图,你必须确保已经访问过的节点不是你刚刚来自的节点。这就是我试图在
else声明中捕捉到的逻辑。 -
@CadeBryant 当只有 1 个节点指向自身时,无法检测到循环。
标签: cycle microsoft-distributed-file-system undirected-graph