using System; using System.Collections.Generic; using System.Diagnostics; public class Test { public static void Main() { var tree = new List { new Data { Id = 1, Items = new List { new Data {Id = 11}, new Data {Id = 12}, } }, new Data { Id = 2, Items = new List { new Data {Id = 21}, new Data {Id = 22}, } }, }; var selected = new Data(); var output = (Action) (Console.WriteLine); //(Action) (Debug.WriteLine); var comparator = (Func) ((x, sel) => true); // ReSharper disable SpecifyACultureInStringConversionExplicitly // не использую при конверсии .ToString(CultureInfo.InvariantCulture) // т.к. данные выводятся пользователю var action = (Action, Data>) ((tr, x) => output(x.Id.ToString())); // ReSharper restore SpecifyACultureInStringConversionExplicitly Console.WriteLine("Calling Depth-first Pre-order Recursive variant"); new Traverser().DepthFirstPreOrderRecursive(tree, selected, comparator, action); Console.WriteLine("Calling Depth-First reversed-Pre-Order on-Stack variant"); new Traverser().DepthFirstPreOrderStack(tree, selected, comparator, action); Console.WriteLine("Calling Breadth-first on-Queue variant"); new Traverser().BreadthFirstQueue(tree, selected, comparator, action); } } public class Traverser { public void DepthFirstPreOrderRecursive(List items, Data selected, Func comparator, Action, Data> action) { foreach (var x in items) { if (comparator(x, selected)) { action(items, x); } DepthFirstPreOrderRecursive(x.Items, selected, comparator, action); } } public void DepthFirstPreOrderStack(List items, Data selected, Func comparator, Action, Data> action) { var stack = new Stack(items); while (stack.Count != 0) { var x = stack.Pop(); if (comparator(x, selected)) { action(items, x); } foreach (var child in x.Items) { stack.Push(child); } } } public void BreadthFirstQueue(List items, Data selected, Func comparator, Action, Data> action) { var queue = new Queue(items); while (queue.Count != 0) { var x = queue.Dequeue(); if (comparator(x, selected)) { action(items, x); } foreach (var child in x.Items) { queue.Enqueue(child); } } } } public class Data { public int Id { get; set; } public List Items { get; set; } public Data() { Items = new List(); } }