From 381355beb99fbdf2b595ff35db7457dceecbb3c8 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 8 Oct 2018 14:21:54 -0400 Subject: [PATCH] perf: BreadthFirstSearchPathManyDestinations returns an IEnumerable to support early termination --- ICD.Common.Utils.Tests/RecursionUtilsTest.cs | 6 ++++-- ICD.Common.Utils/RecursionUtils.cs | 21 +++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ICD.Common.Utils.Tests/RecursionUtilsTest.cs b/ICD.Common.Utils.Tests/RecursionUtilsTest.cs index 8a32c50..c9ed3a8 100644 --- a/ICD.Common.Utils.Tests/RecursionUtilsTest.cs +++ b/ICD.Common.Utils.Tests/RecursionUtilsTest.cs @@ -180,9 +180,11 @@ namespace ICD.Common.Utils.Tests { Assert.Throws(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 1 }, null)); Assert.Throws(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, null, Graph)); - Assert.IsEmpty(RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 5 }, Graph)); + Assert.AreEqual(0, RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 5 }, Graph).Count()); - Dictionary> paths = RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 21, 22, 31, 43, 62 }, WideGraph); + Dictionary> paths = + RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] {21, 22, 31, 43, 62}, WideGraph) + .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); //Make sure all paths were found Assert.IsTrue(paths.Keys.Contains(21)); diff --git a/ICD.Common.Utils/RecursionUtils.cs b/ICD.Common.Utils/RecursionUtils.cs index 425c2ee..8ff38bf 100644 --- a/ICD.Common.Utils/RecursionUtils.cs +++ b/ICD.Common.Utils/RecursionUtils.cs @@ -235,12 +235,16 @@ namespace ICD.Common.Utils return null; } + [NotNull] - public static Dictionary> BreadthFirstSearchManyDestinations(T root, + public static IEnumerable>> BreadthFirstSearchManyDestinations(T root, IEnumerable destinations, Func> getChildren) { + if (destinations == null) + throw new ArgumentNullException("destinations"); + if (getChildren == null) throw new ArgumentNullException("getChildren"); @@ -248,7 +252,7 @@ namespace ICD.Common.Utils } [NotNull] - public static Dictionary> BreadthFirstSearchPathManyDestinations(T root, + public static IEnumerable>> BreadthFirstSearchPathManyDestinations(T root, IEnumerable destinations, Func> @@ -272,12 +276,12 @@ namespace ICD.Common.Utils foreach (T destination in destinationsToBeProcessed.Where(destination => comparer.Equals(root, destination)).ToArray()) { - destinationsToBeProcessed.Remove(destination); - pathsToReturn.Add(destination, new[] {root}); + destinationsToBeProcessed.Remove(destination); + yield return new KeyValuePair>(destination, new[] {root}); } if (destinationsToBeProcessed.Count == 0) - return pathsToReturn; + yield break; Queue queue = new Queue(); queue.Enqueue(root); @@ -298,15 +302,14 @@ namespace ICD.Common.Utils destinationsToBeProcessed.Where(destination => comparer.Equals(closureNode, destination)).ToArray()) { destinationsToBeProcessed.Remove(destination); - pathsToReturn.Add(destination, GetPath(destination, root, nodeParents, comparer).Reverse()); + + yield return new KeyValuePair>(destination, GetPath(destination, root, nodeParents, comparer).Reverse()); } if (destinationsToBeProcessed.Count == 0) - return pathsToReturn; + break; } } - - return pathsToReturn; } ///