/// <summary> // Walks a Node in a depth-first/pre-order manner without recursion. // It returns a series of "events" that indicate one of three things: // - whether it has enters into a node // - whether it has exited from a node (i.e. it is finished with that container and its children) /// </summary> /// <param name="node"></param> /// <param name="enum_children"></param> /// <param name="enter_node"></param> /// <returns></returns> public static IEnumerable <WalkEvent <T> > Walk <T>(T node, Traversal.EnumerateChildren <T> enum_children, EnterNode <T> enter_node) { var stack = new Stack <WalkState <T> >(); // put the first item on the stack stack.Push(new WalkState <T>(node)); // As long as something is on the stack, we are not done while (stack.Count > 0) { var cur_item = stack.Pop(); if (cur_item.Entered == false) { var walkevent = new WalkEvent <T>(cur_item.Node, WalkEventType.Enter); yield return(walkevent); cur_item.Entered = true; stack.Push(cur_item); if (enter_node(cur_item.Node)) { foreach (var child in Traversal.efficient_reverse(enum_children(cur_item.Node))) { stack.Push(new WalkState <T>(child)); } } } else { var walkevent = new WalkEvent <T>(cur_item.Node, WalkEventType.Exit); yield return(walkevent); } } }
public static IEnumerable <WalkEvent <T> > Walk <T>(T node, Traversal.EnumerateChildren <T> enum_children) { return(Walk(node, enum_children, n => true)); }