60 lines
1.7 KiB
C#
60 lines
1.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using JD.Kernel.StaticHelpers;
|
|
|
|
namespace JD.Collections.Utilities
|
|
{
|
|
public abstract class GraphWalker<T>
|
|
{
|
|
#region Methods
|
|
|
|
protected abstract IEnumerable<T> GetDependenciesOf(T item);
|
|
|
|
public bool CanReach(T source, T target)
|
|
{
|
|
Throw.IfNull(source, "source");
|
|
Throw.IfNull(target, "target");
|
|
|
|
Set<T> reachable = new Set<T>();
|
|
Predicate<T> isTarget = targetToTest => Equals(target, targetToTest);
|
|
return CanReach(source, isTarget, reachable);
|
|
}
|
|
|
|
public bool CanReach(T source, Predicate<T> target)
|
|
{
|
|
Throw.IfNull(source, "source");
|
|
Throw.IfNull(target, "target");
|
|
|
|
Set<T> reachable = new Set<T>();
|
|
return CanReach(source, target, reachable);
|
|
}
|
|
|
|
private bool CanReach(T source, Predicate<T> isTarget, Set<T> reachable)
|
|
{
|
|
if (isTarget(source))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (reachable.Add(source))
|
|
{
|
|
return GetDependenciesOf(source).Any(dependency => CanReach(dependency, isTarget, reachable));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if the source can reach the target in one step.
|
|
/// </summary>
|
|
public bool IsAdjacent(T source, Predicate<T> isTrarget)
|
|
{
|
|
// It could have used a Func<T, bool> directly but I prefer the predicate (they are more explicit).
|
|
|
|
return GetDependenciesOf(source).Any(dependency => isTrarget(dependency));
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|