PowerShellUtils/Lib/Traverser.cs

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using PowerShellStandardModule1.Models;
 
namespace PowerShellStandardModule1.Lib;
 
public abstract class Traverser<T>
{
    protected abstract void Enqueue(T value);
 
    protected abstract bool IsEmpty { get; }
    protected abstract T Dequeue();
}
 
public abstract class BasicTraverser<T> : Traverser<T>
{
    protected abstract IEnumerable<T> GetChildren(T value);
 
    public IEnumerable<T> Invoke(T root)
    {
        Enqueue(root);
        while (!IsEmpty)
        {
            var value = Dequeue();
            yield return value;
 
            Process(value);
        }
    }
 
    private void Process(T node)
    {
        foreach (var child in GetChildren(node))
        {
            Enqueue(child);
        }
    }
}
 
public abstract class TreeTraverser<T> : Traverser<TreeNode<T>>
{
    public IEnumerable<TreeNode<T>> Invoke(T node)
    {
        var root = new TreeNode<T> { Value = node };
        Enqueue(root);
        while (!IsEmpty)
        {
            var value = Dequeue();
            yield return value;
 
            Process(value);
        }
    }
 
 
    private void Process(TreeNode<T> node)
    {
        var parentHeightPlusOne = node.Height + 1;
 
        var children = GetChildren(node)
           .Select(
                (x, i) => new TreeNode<T>
                {
                    Value = x,
                    Height = parentHeightPlusOne,
                    Parent = node,
                    Index = i
                }
            )
           .ToImmutableList();
 
        node.Children = children;
        foreach (var child in children)
        {
            Enqueue(child);
        }
    }
 
    protected abstract IEnumerable<T> GetChildren(TreeNode<T> value);
}
 
public abstract class BfsTraverser<T> : BasicTraverser<T>
{
    private readonly Queue<T> _queue = new();
 
    protected override void Enqueue(T value)
    {
        _queue.Enqueue(value);
    }
 
    protected override bool IsEmpty => _queue.Count == 0;
 
    protected override T Dequeue()
    {
        return _queue.Dequeue();
    }
}
 
public abstract class BfsDetailedTraverser<T> : TreeTraverser<T>
{
    private readonly Queue<TreeNode<T>> _queue = new();
 
    protected override void Enqueue(TreeNode<T> value)
    {
        _queue.Enqueue(value);
    }
 
    protected override bool IsEmpty => _queue.Count == 0;
 
    protected override TreeNode<T> Dequeue()
    {
        return _queue.Dequeue();
    }
}
 
public abstract class DfsTraverser<T> : BasicTraverser<T>
{
    private readonly Stack<T> _stack = new();
 
    protected override void Enqueue(T value)
    {
        _stack.Push(value);
    }
 
    protected override bool IsEmpty => _stack.Count == 0;
 
    protected override T Dequeue()
    {
        return _stack.Pop();
    }
}
 
public abstract class DfsDetailedTraverser<T> : TreeTraverser<T>
{
    private readonly Stack<TreeNode<T>> _stack = new();
 
    protected override void Enqueue(TreeNode<T> value)
    {
        _stack.Push(value);
    }
 
    protected override bool IsEmpty => _stack.Count == 0;
 
    protected override TreeNode<T> Dequeue()
    {
        return _stack.Pop();
    }
}