using System;
using System.Collections.Generic;
using System.Diagnostics;
public class Test
{
public static void Main()
{
var tree = new List<Data>
{
new Data
{
Id = 1,
Items = new List<Data>
{
new Data {Id = 11},
new Data {Id = 12},
}
},
new Data
{
Id = 2,
Items = new List<Data>
{
new Data {Id = 21},
new Data {Id = 22},
}
},
};
var selected = new Data();
var output =
(Action<string>) (Console.WriteLine);
//(Action<string>) (Debug.WriteLine);
var comparator =
(Func<Data, Data, bool>) ((x, sel) => true);
// ReSharper disable SpecifyACultureInStringConversionExplicitly
// не использую при конверсии .ToString(CultureInfo.InvariantCulture)
// т.к. данные выводятся пользователю
var action =
(Action<List<Data>, 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<Data> items, Data selected, Func<Data, Data, bool> comparator, Action<List<Data>, Data> action)
{
foreach (var x in items)
{
if (comparator(x, selected))
{
action(items, x);
}
DepthFirstPreOrderRecursive(x.Items, selected, comparator, action);
}
}
public void DepthFirstPreOrderStack(List<Data> items, Data selected, Func<Data, Data, bool> comparator, Action<List<Data>, Data> action)
{
var stack = new Stack<Data>(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<Data> items, Data selected, Func<Data, Data, bool> comparator, Action<List<Data>, Data> action)
{
var queue = new Queue<Data>(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<Data> Items { get; set; }
public Data()
{
Items = new List<Data>();
}
}
ICAgIHVzaW5nIFN5c3RlbTsKICAgIHVzaW5nIFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljOwogICAgdXNpbmcgU3lzdGVtLkRpYWdub3N0aWNzOwoKICAgIHB1YmxpYyBjbGFzcyBUZXN0CiAgICB7CiAgICAgICAgcHVibGljIHN0YXRpYyB2b2lkIE1haW4oKQogICAgICAgIHsKICAgICAgICAgICAgdmFyIHRyZWUgPSBuZXcgTGlzdDxEYXRhPgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIG5ldyBEYXRhCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIElkID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEl0ZW1zID0gbmV3IExpc3Q8RGF0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBEYXRhIHtJZCA9IDExfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IERhdGEge0lkID0gMTJ9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICBuZXcgRGF0YQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJZCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJdGVtcyA9IG5ldyBMaXN0PERhdGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgRGF0YSB7SWQgPSAyMX0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBEYXRhIHtJZCA9IDIyfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICB2YXIgc2VsZWN0ZWQgPSBuZXcgRGF0YSgpOwoKICAgICAgICAgICAgdmFyIG91dHB1dCA9CiAgICAgICAgICAgICAgICAoQWN0aW9uPHN0cmluZz4pIChDb25zb2xlLldyaXRlTGluZSk7CiAgICAgICAgICAgICAgICAvLyhBY3Rpb248c3RyaW5nPikgKERlYnVnLldyaXRlTGluZSk7CgogICAgICAgICAgICB2YXIgY29tcGFyYXRvciA9CiAgICAgICAgICAgICAgICAoRnVuYzxEYXRhLCBEYXRhLCBib29sPikgKCh4LCBzZWwpID0+IHRydWUpOwoKICAgICAgICAgICAgLy8gUmVTaGFycGVyIGRpc2FibGUgU3BlY2lmeUFDdWx0dXJlSW5TdHJpbmdDb252ZXJzaW9uRXhwbGljaXRseQogICAgICAgICAgICAvLyDQvdC1INC40YHQv9C+0LvRjNC30YPRjiDQv9GA0Lgg0LrQvtC90LLQtdGA0YHQuNC4IC5Ub1N0cmluZyhDdWx0dXJlSW5mby5JbnZhcmlhbnRDdWx0dXJlKQogICAgICAgICAgICAvLyDRgi7Qui4g0LTQsNC90L3Ri9C1INCy0YvQstC+0LTRj9GC0YHRjyDQv9C+0LvRjNC30L7QstCw0YLQtdC70Y4KICAgICAgICAgICAgdmFyIGFjdGlvbiA9CiAgICAgICAgICAgICAgICAoQWN0aW9uPExpc3Q8RGF0YT4sIERhdGE+KSAoKHRyLCB4KSA9PiBvdXRwdXQoeC5JZC5Ub1N0cmluZygpKSk7CiAgICAgICAgICAgIC8vIFJlU2hhcnBlciByZXN0b3JlIFNwZWNpZnlBQ3VsdHVyZUluU3RyaW5nQ29udmVyc2lvbkV4cGxpY2l0bHkKCiAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJDYWxsaW5nIERlcHRoLWZpcnN0IFByZS1vcmRlciBSZWN1cnNpdmUgdmFyaWFudCIpOwogICAgICAgICAgICBuZXcgVHJhdmVyc2VyKCkuRGVwdGhGaXJzdFByZU9yZGVyUmVjdXJzaXZlKHRyZWUsIHNlbGVjdGVkLCBjb21wYXJhdG9yLCBhY3Rpb24pOwoKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIkNhbGxpbmcgRGVwdGgtRmlyc3QgcmV2ZXJzZWQtUHJlLU9yZGVyIG9uLVN0YWNrIHZhcmlhbnQiKTsKICAgICAgICAgICAgbmV3IFRyYXZlcnNlcigpLkRlcHRoRmlyc3RQcmVPcmRlclN0YWNrKHRyZWUsIHNlbGVjdGVkLCBjb21wYXJhdG9yLCBhY3Rpb24pOwoKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIkNhbGxpbmcgQnJlYWR0aC1maXJzdCBvbi1RdWV1ZSB2YXJpYW50Iik7CiAgICAgICAgICAgIG5ldyBUcmF2ZXJzZXIoKS5CcmVhZHRoRmlyc3RRdWV1ZSh0cmVlLCBzZWxlY3RlZCwgY29tcGFyYXRvciwgYWN0aW9uKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIGNsYXNzIFRyYXZlcnNlcgogICAgewogICAgICAgIHB1YmxpYyB2b2lkIERlcHRoRmlyc3RQcmVPcmRlclJlY3Vyc2l2ZShMaXN0PERhdGE+IGl0ZW1zLCBEYXRhIHNlbGVjdGVkLCBGdW5jPERhdGEsIERhdGEsIGJvb2w+IGNvbXBhcmF0b3IsIEFjdGlvbjxMaXN0PERhdGE+LCBEYXRhPiBhY3Rpb24pCiAgICAgICAgewogICAgICAgICAgICBmb3JlYWNoICh2YXIgeCBpbiBpdGVtcykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKGNvbXBhcmF0b3IoeCwgc2VsZWN0ZWQpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGFjdGlvbihpdGVtcywgeCk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgRGVwdGhGaXJzdFByZU9yZGVyUmVjdXJzaXZlKHguSXRlbXMsIHNlbGVjdGVkLCBjb21wYXJhdG9yLCBhY3Rpb24pOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgdm9pZCBEZXB0aEZpcnN0UHJlT3JkZXJTdGFjayhMaXN0PERhdGE+IGl0ZW1zLCBEYXRhIHNlbGVjdGVkLCBGdW5jPERhdGEsIERhdGEsIGJvb2w+IGNvbXBhcmF0b3IsIEFjdGlvbjxMaXN0PERhdGE+LCBEYXRhPiBhY3Rpb24pCiAgICAgICAgewogICAgICAgICAgICB2YXIgc3RhY2sgPSBuZXcgU3RhY2s8RGF0YT4oaXRlbXMpOwogICAgICAgICAgICB3aGlsZSAoc3RhY2suQ291bnQgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdmFyIHggPSBzdGFjay5Qb3AoKTsKCiAgICAgICAgICAgICAgICBpZiAoY29tcGFyYXRvcih4LCBzZWxlY3RlZCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgYWN0aW9uKGl0ZW1zLCB4KTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBmb3JlYWNoICh2YXIgY2hpbGQgaW4geC5JdGVtcykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBzdGFjay5QdXNoKGNoaWxkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIHZvaWQgQnJlYWR0aEZpcnN0UXVldWUoTGlzdDxEYXRhPiBpdGVtcywgRGF0YSBzZWxlY3RlZCwgRnVuYzxEYXRhLCBEYXRhLCBib29sPiBjb21wYXJhdG9yLCBBY3Rpb248TGlzdDxEYXRhPiwgRGF0YT4gYWN0aW9uKQogICAgICAgIHsKICAgICAgICAgICAgdmFyIHF1ZXVlID0gbmV3IFF1ZXVlPERhdGE+KGl0ZW1zKTsKICAgICAgICAgICAgd2hpbGUgKHF1ZXVlLkNvdW50ICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHZhciB4ID0gcXVldWUuRGVxdWV1ZSgpOwoKICAgICAgICAgICAgICAgIGlmIChjb21wYXJhdG9yKHgsIHNlbGVjdGVkKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBhY3Rpb24oaXRlbXMsIHgpOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIGZvcmVhY2ggKHZhciBjaGlsZCBpbiB4Lkl0ZW1zKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHF1ZXVlLkVucXVldWUoY2hpbGQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBjbGFzcyBEYXRhCiAgICB7CiAgICAgICAgcHVibGljIGludCBJZCB7IGdldDsgc2V0OyB9CiAgICAgICAgcHVibGljIExpc3Q8RGF0YT4gSXRlbXMgeyBnZXQ7IHNldDsgfQogICAgICAgIHB1YmxpYyBEYXRhKCkKICAgICAgICB7CiAgICAgICAgICAgIEl0ZW1zID0gbmV3IExpc3Q8RGF0YT4oKTsKICAgICAgICB9CiAgICB9