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