所以我已经成功实现了递归tarjan,它为我提供了图的SCC
我的递归实现如下:
public void DFSRecursive(long currentNode){
low[currentNode] = preCount++;
visited[currentNode] = true;
stack.Push(currentNode);
long minimum = low[currentNode];
foreach(long successorNode in SuccessorMap[currentNode])
{
if(!visited[successorNode])
{
DFSRecursive(successorNode);
}
if(low[successorNode] < minimum)
{
minimum = low[successorNode];
}
}
if(minimum < low[currentNode])
{
low[currentNode] = minimum;
return;
}
List<long> component = new List<long>();
long stackTop;
do
{
stackTop = stack.Pop();
component.Add(stackTop);
}
while(stackTop != currentNode);
SCComponent.Add(component);
}
现在,我需要将其转换为迭代解决方案。我已经检查了很多资源来帮助我,其中包括一个非常类似的SO问题(Non-recursive version of Tarjan's algorithm)。我不能使用枚举器,因为我必须处理长值,并且当前状态的后继索引已存储在Dictionary(SuccessorMap [])中(需要处理节点数大于50亿的图)。
我已遵循将递归解决方案转换为迭代解决方案的一般准则:
在循环开始时设置变量,并从本地弹出 堆栈
public void DFSIterative(long currentNode)
{
var internalStack = new Stack<long>();
low[currentNode] = preCount++;
stack.Push(currentNode);
long minimum = low[currentNode];
internalStack.Push(currentNode);
while(!(internalStack.Count == 0))
{
currentNode = internalStack.Pop();
visited[currentNode] = true;
foreach(long successorNode in SuccessorMap[currentNode])
{
if(!visited[successorNode])
{
internalStack.Push(successorNode);
}
if(low[successorNode] < minimum)
{
minimum = low[successorNode];
}
}
if(minimum < low[currentNode])
{
low[currentNode] = minimum;
return;
}
}
List<long> component = new List<long>();
long stackTop;
do
{
stackTop = stack.Pop();
component.Add(w);
}
while(stackTop != currentNode);
SCComponent.Add(component);
}
我认识到迭代方法中的do-while循环将始终抛出InvalidOperationException(stack empty)
,但我还没有弄清楚迭代实现递归do-while的方法。
真的很感谢能帮助我的各种帮助。