RecursionUtils methods for finding a path in a graph

This commit is contained in:
Chris Cameron
2017-09-26 13:52:53 -04:00
parent 2a139e4f3d
commit f87470da41

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICD.Common.Properties;
namespace ICD.Common.Utils
{
@@ -14,6 +16,9 @@ namespace ICD.Common.Utils
/// <returns></returns>
public static IEnumerable<T> BreadthFirstSearch<T>(T root, Func<T, IEnumerable<T>> getChildren)
{
if (getChildren == null)
throw new ArgumentNullException("getChildren");
Queue<T> process = new Queue<T>();
process.Enqueue(root);
@@ -26,5 +31,84 @@ namespace ICD.Common.Utils
process.Enqueue(child);
}
}
/// <summary>
/// Returns the shortest path from root to destination via breadth-first search.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="root"></param>
/// <param name="destination"></param>
/// <param name="getChildren"></param>
/// <returns></returns>
[CanBeNull]
public static IEnumerable<T> BreadthFirstSearchPath<T>(T root, T destination, Func<T, IEnumerable<T>> getChildren)
{
if (getChildren == null)
throw new ArgumentNullException("getChildren");
return BreadthFirstSearchPath(root, destination, getChildren, EqualityComparer<T>.Default);
}
/// <summary>
/// Returns the shortest path from root to destination via breadth-first search.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="root"></param>
/// <param name="destination"></param>
/// <param name="getChildren"></param>
/// <param name="comparer"></param>
/// <returns></returns>
[CanBeNull]
public static IEnumerable<T> BreadthFirstSearchPath<T>(T root, T destination, Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T> comparer)
{
if (getChildren == null)
throw new ArgumentNullException("getChildren");
if (comparer == null)
throw new ArgumentNullException("comparer");
Queue<T> queue = new Queue<T>();
queue.Enqueue(root);
Dictionary<T, T> nodeParents = new Dictionary<T, T>();
while (queue.Count > 0)
{
T current = queue.Dequeue();
foreach (T node in getChildren(current))
{
if (nodeParents.ContainsKey(node))
continue;
queue.Enqueue(node);
nodeParents.Add(node, current);
// Found a path to the destination
if (comparer.Equals(node, destination))
return GetPath(destination, nodeParents).Reverse();
}
}
return null;
}
/// <summary>
/// Walks through a map of nodes from the starting point.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="start"></param>
/// <param name="nodeParents"></param>
/// <returns></returns>
private static IEnumerable<T> GetPath<T>(T start, IDictionary<T, T> nodeParents)
{
while (true)
{
yield return start;
if (!nodeParents.TryGetValue(start, out start))
break;
}
}
}
}