Поиск в ширину обычно выполняется с помощью очереди , поиск в глубину с использованием стека .
Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while(q.Count > 0)
{
Node current = q.Dequeue();
if(current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
DoSomething(current);
}
В качестве альтернативы проверке null
после удаления из очереди вы можете проверить перед добавлением в очередь. Я не компилировал код, поэтому он может содержать небольшие ошибки.
Модная (но более медленная) версия, которая хорошо интегрируется с LINQ:
public static IEnumerable<T> BreadthFirstTopDownTraversal<T>(T root, Func<T, IEnumerable<T>> children)
{
var q = new Queue<T>();
q.Enqueue(root);
while (q.Count > 0)
{
T current = q.Dequeue();
yield return current;
foreach (var child in children(current))
q.Enqueue(child);
}
}
Который можно использовать вместе со свойством Children
в Node
:
IEnumerable<Node> Children { get { return new []{ Left, Right }.Where(x => x != null); } }
...
foreach(var node in BreadthFirstTopDownTraversal(root, node => node.Children))
{
...
}