// <summary> // Walk the graph like it was a tree from the root - if you encounter a cycle, stop further walking // and continue with the next node // </summary> // <param name="opeartion"></param> // <param name="state"></param> public void BreadthFirstSearchOperation(GraphNodeOperationDelegate operation, object state) { Queue <IGraphNode> pendingNodes = new Queue <IGraphNode>(); pendingNodes.Enqueue(this); List <IGraphNode> visitedNodes = new List <IGraphNode>(); while (pendingNodes.Count != 0) { IGraphNode node = pendingNodes.Dequeue(); if (visitedNodes.Contains(node)) { // cycle - already seen this node // continue; } else { visitedNodes.Add(node); } operation(node, state); foreach (IGraphNode child in node.Children) { pendingNodes.Enqueue(child); } } }
public void DepthFirstSearchOperation(GraphNodeOperationDelegate preVisit, GraphNodeOperationDelegate postVisit, object state) { // nothing happens unless one operation is provided if (preVisit == null && postVisit == null) { return; } // we must be able to distinguish these for the algorithm below to work if (preVisit == postVisit) { throw new InvalidOperationException("Operations must be different."); } List <IGraphNode> visitedNodes = new List <IGraphNode>(); Stack <DepthFirstWalkInfo> frames = new Stack <DepthFirstWalkInfo>(); frames.Push(new DepthFirstWalkInfo { CurrentNode = this, Operation = preVisit }); while (frames.Count > 0) { DepthFirstWalkInfo current = frames.Pop(); if (visitedNodes.Contains(current.CurrentNode)) { if (current.Operation == preVisit) { continue; } } else { visitedNodes.Add(current.CurrentNode); } if (current.Operation != null) { current.Operation(current.CurrentNode, state); } if (current.Operation != postVisit) { frames.Push(new DepthFirstWalkInfo { CurrentNode = current.CurrentNode, Operation = postVisit }); // this goes into the stack in reverse order of what we need, // put onto one stack then another to reverse it Stack <DepthFirstWalkInfo> tempStack = new Stack <DepthFirstWalkInfo>(); foreach (IGraphNode child in current.CurrentNode.Children) { tempStack.Push(new DepthFirstWalkInfo { CurrentNode = child, Operation = preVisit }); } while (tempStack.Count > 0) { frames.Push(tempStack.Pop()); } } } }
public void DepthFirstSearchOperation(GraphNodeOperationDelegate operation, object state) { DepthFirstSearchOperation(operation, null, state); }