using System; using System.Collections.Generic; namespace Chernobyl.Collections.Generic.Hierarchy { /// /// An enumerator that enumerates through a tree in depth first order /// (http://en.wikipedia.org/wiki/Depth-first_search). This enumerator /// does not operate on a specific "tree type", instead, it operates on /// types that are structured like tree nodes, i.e. the class holds instances /// of it's own type; for example: /// /// class Foobar /// { /// public List{Foobar} Children { get; } /// } /// /// /// The type that contains a list of instances of it's /// own type (a class that acts as a node in a tree). public class DepthFirstEnumerator : TreeEnumerator { /// /// Initializes a new instance of the /// class. /// /// The inclusive node to start from (it will /// become the first value of . /// The method that retrieves the /// from an instance of type /// . Typically, it will look something like /// this (using a lambda expression): /// /// foobar => foobar.Children.GetEnumerator(); /// /// public DepthFirstEnumerator(T startingNode, Func> getChildEnumerator) : base(startingNode, getChildEnumerator) { } /// /// Advances the enumerator to the next element of the collection. /// /// /// true if the enumerator was successfully advanced to the next element; /// false if the enumerator has passed the end of the collection. /// /// The collection was /// modified after the enumerator was created. public override bool MoveNext() { bool result = true; if(Started == false) { Started = true; Current = Start; EnumeratorLevels.AddLast(GetChildEnumerator(Current)); } else { bool finished = false; while (finished == false) { // have we gone through the entire tree? if (EnumeratorLevels.Last == null) { finished = true; result = false; } else if (EnumeratorLevels.Last.Value.MoveNext() == true) { // drop down into the next 'level' of the tree by // appending the children enumerator Current = EnumeratorLevels.Last.Value.Current; EnumeratorLevels.AddLast(GetChildEnumerator(Current)); finished = true; } else // We are finished with the last enumerator we added EnumeratorLevels.RemoveLast(); } } return result; } } }