I have the following method that is recursive, but I'm getting an StackOverflow because the list is too long. Please, someone with experience could convert this piece of code to iterative?
private List<Node> FindWayFrom(
Node srcNode,
Node dstNode,
List<Node> way,
List<Node> visitedNodes)
{
if (visitedNodes.Contains(srcNode))
return null;
visitedNodes.Add(srcNode);
way.Add(srcNode);
IList connectedNodes = GetConnectedNodes(srcNode);
if (connectedNodes == null || connectedNodes.Count == 0)
return null;
foreach (Node node in connectedNodes)
{
if (node == dstNode) return way;
List<Node> result = FindWayFrom(node, dstNode, way, visitedNodes);
if (result != null)
return result;
//It is not the correct way. Remove current changeset.
way.Remove(node);
}
return null;
}
I'll add somethings to your
Node
classAnd (I think you want to find a path from source to destination), I suggest use Queue to find it simply, Also you should improve your data structure, currently your data structure is very poor and seems you code in functional language (not c#):
Code is not tested may be has compile errors and is not as efficient as possible, but simply is fixable, but Idea is using queue, and marking visited node, also for tracking the path you should have some information about current created path, then going backward to output it.
You need to use a stack instead of calling the routine recusivly.
Place a while loop around the whole routine to check if your local stack has items if it does pop the item.
The line where you are calling the method again push those details onto the stack.
At the start of the routine push the incoming method details.
The most common way to do this is to push objects to the stack just as if you were making a function call, and operate on that stack inside the iteration
Way to go from recursion to iteration
Here's a quick attempt to implement this:
It was a nice brain teaser and a welcome distraction. While I haven't tested it thoroughly I ran different scenarios: no path exists, path exists, loop exists, they all returned a valid result.
The tricky part (conceptually) is to keep track of which child path you are currently descending into. I store this in
Frame.NextChild
.Update: I've refactored the code. The main loop is now very simple and the two main concepts (descending and backtracking) are now nicely encapsulated in separate methods.