using System; using System.Collections.Generic; using System.Linq; namespace ZeroLevel.Services.Trees { public static class TreesVisitor { /// /// Extract tree branches to plain array /// /// Node type /// Tree root /// Extractor of node children /// Array of tree branches public static List ExtractBranches(T root, Func> childrenExtractor) { if (root == null) throw new ArgumentNullException(nameof(root)); if (childrenExtractor == null) throw new ArgumentNullException(nameof(childrenExtractor)); var result = new List(); TraversTreeBrunches(root, childrenExtractor, brunch => { result.Add(brunch.ToArray()); }); return result; } /// /// Выделяет все ветви дерева, возвращая массив ветвей состоящий из специфицированных значений узлов /// /// Тип узлов дерева /// Тип значений для возвращаемых элементов ветвей /// Корень /// Выделяет дочерние узлы для текущего узла /// Выделяет значение узла /// Список ветвей дерева public static List SpecifyExtractBranches(T root, Func> childrenExtractor, Func codeExtractor) { if (root == null) throw new ArgumentNullException(nameof(root)); if (childrenExtractor == null) throw new ArgumentNullException(nameof(childrenExtractor)); if (codeExtractor == null) throw new ArgumentNullException(nameof(codeExtractor)); var result = new List(); TraversTreeBrunches(root, childrenExtractor, brunch => { result.Add(brunch.Select(i => codeExtractor(i)).ToArray()); }); return result; } /// /// Выполняет обход ветвей дерева /// /// Тип узлов дерева /// Корень /// Выделяет дочерние узлы для текущего узла /// Обработчик ветви public static void TraversTreeBrunches(T root, Func> childrenExtractor, Action> handler) { if (root == null) throw new ArgumentNullException(nameof(root)); if (childrenExtractor == null) throw new ArgumentNullException(nameof(childrenExtractor)); if (handler == null) throw new ArgumentNullException(nameof(handler)); var brunch = new List(); brunch.Add(root); foreach (var child in childrenExtractor(root)) { TraversNode(child, brunch, childrenExtractor, handler); } } private static void TraversNode(T node, List brunch, Func> childrenExtractor, Action> handler) { if (node == null) { handler(brunch); return; } var currentBrunch = new List(brunch); currentBrunch.Add(node); var children = childrenExtractor(node); if (children != null && children.Any()) { foreach (var child in childrenExtractor(node)) { TraversNode(child, currentBrunch, childrenExtractor, handler); } } else { handler(currentBrunch); } } } }