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;
}
}
}