perf: BreadthFirstSearchPathManyDestinations returns an IEnumerable to support early termination

This commit is contained in:
Chris Cameron
2018-10-08 14:21:54 -04:00
parent 2a25c3d733
commit 381355beb9
2 changed files with 16 additions and 11 deletions

View File

@@ -180,9 +180,11 @@ namespace ICD.Common.Utils.Tests
{ {
Assert.Throws<ArgumentNullException>(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 1 }, null)); Assert.Throws<ArgumentNullException>(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 1 }, null));
Assert.Throws<ArgumentNullException>(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, null, Graph)); Assert.Throws<ArgumentNullException>(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, null, Graph));
Assert.IsEmpty(RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 5 }, Graph)); Assert.AreEqual(0, RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 5 }, Graph).Count());
Dictionary<int, IEnumerable<int>> paths = RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 21, 22, 31, 43, 62 }, WideGraph); Dictionary<int, IEnumerable<int>> paths =
RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] {21, 22, 31, 43, 62}, WideGraph)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
//Make sure all paths were found //Make sure all paths were found
Assert.IsTrue(paths.Keys.Contains(21)); Assert.IsTrue(paths.Keys.Contains(21));

View File

@@ -235,12 +235,16 @@ namespace ICD.Common.Utils
return null; return null;
} }
[NotNull] [NotNull]
public static Dictionary<T, IEnumerable<T>> BreadthFirstSearchManyDestinations<T>(T root, public static IEnumerable<KeyValuePair<T, IEnumerable<T>>> BreadthFirstSearchManyDestinations<T>(T root,
IEnumerable<T> destinations, IEnumerable<T> destinations,
Func<T, IEnumerable<T>> Func<T, IEnumerable<T>>
getChildren) getChildren)
{ {
if (destinations == null)
throw new ArgumentNullException("destinations");
if (getChildren == null) if (getChildren == null)
throw new ArgumentNullException("getChildren"); throw new ArgumentNullException("getChildren");
@@ -248,7 +252,7 @@ namespace ICD.Common.Utils
} }
[NotNull] [NotNull]
public static Dictionary<T, IEnumerable<T>> BreadthFirstSearchPathManyDestinations<T>(T root, public static IEnumerable<KeyValuePair<T, IEnumerable<T>>> BreadthFirstSearchPathManyDestinations<T>(T root,
IEnumerable<T> IEnumerable<T>
destinations, destinations,
Func<T, IEnumerable<T>> Func<T, IEnumerable<T>>
@@ -272,12 +276,12 @@ namespace ICD.Common.Utils
foreach (T destination in foreach (T destination in
destinationsToBeProcessed.Where(destination => comparer.Equals(root, destination)).ToArray()) destinationsToBeProcessed.Where(destination => comparer.Equals(root, destination)).ToArray())
{ {
destinationsToBeProcessed.Remove(destination); destinationsToBeProcessed.Remove(destination);
pathsToReturn.Add(destination, new[] {root}); yield return new KeyValuePair<T, IEnumerable<T>>(destination, new[] {root});
} }
if (destinationsToBeProcessed.Count == 0) if (destinationsToBeProcessed.Count == 0)
return pathsToReturn; yield break;
Queue<T> queue = new Queue<T>(); Queue<T> queue = new Queue<T>();
queue.Enqueue(root); queue.Enqueue(root);
@@ -298,15 +302,14 @@ namespace ICD.Common.Utils
destinationsToBeProcessed.Where(destination => comparer.Equals(closureNode, destination)).ToArray()) destinationsToBeProcessed.Where(destination => comparer.Equals(closureNode, destination)).ToArray())
{ {
destinationsToBeProcessed.Remove(destination); destinationsToBeProcessed.Remove(destination);
pathsToReturn.Add(destination, GetPath(destination, root, nodeParents, comparer).Reverse());
yield return new KeyValuePair<T, IEnumerable<T>>(destination, GetPath(destination, root, nodeParents, comparer).Reverse());
} }
if (destinationsToBeProcessed.Count == 0) if (destinationsToBeProcessed.Count == 0)
return pathsToReturn; break;
} }
} }
return pathsToReturn;
} }
/// <summary> /// <summary>