mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-16 13:15:07 +00:00
RecursionUtils methods for finding a path in a graph
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
namespace ICD.Common.Utils
|
namespace ICD.Common.Utils
|
||||||
{
|
{
|
||||||
@@ -14,6 +16,9 @@ namespace ICD.Common.Utils
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IEnumerable<T> BreadthFirstSearch<T>(T root, Func<T, IEnumerable<T>> getChildren)
|
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>();
|
Queue<T> process = new Queue<T>();
|
||||||
process.Enqueue(root);
|
process.Enqueue(root);
|
||||||
|
|
||||||
@@ -26,5 +31,84 @@ namespace ICD.Common.Utils
|
|||||||
process.Enqueue(child);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user