diff --git a/CHANGELOG.md b/CHANGELOG.md
index e10ace8..5d82b80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- Added RecursionUtils method to get a single clique given a starting node
+ - Breadth First Search can now search graphs in addition to trees
### Changed
- Fixed bug in IcdUriBuilder where Query property behaved differently to UriBuilder
diff --git a/ICD.Common.Utils.Tests/RecursionUtilsTest.cs b/ICD.Common.Utils.Tests/RecursionUtilsTest.cs
index e50e025..ff96110 100644
--- a/ICD.Common.Utils.Tests/RecursionUtilsTest.cs
+++ b/ICD.Common.Utils.Tests/RecursionUtilsTest.cs
@@ -130,7 +130,7 @@ namespace ICD.Common.Utils.Tests
[Test]
public void GetCliqueSingleNodeTest()
{
- int[] clique = RecursionUtils.GetClique(s_CliqueGraph.Keys, 1, n => s_CliqueGraph[n]).ToArray();
+ int[] clique = RecursionUtils.GetClique(1, n => s_CliqueGraph[n]).ToArray();
Assert.AreEqual(4, clique.Length);
Assert.IsTrue(clique.Contains(1));
@@ -138,7 +138,7 @@ namespace ICD.Common.Utils.Tests
Assert.IsTrue(clique.Contains(3));
Assert.IsTrue(clique.Contains(4));
- clique = RecursionUtils.GetClique(s_CliqueGraph.Keys, 5, n => s_CliqueGraph[n]).ToArray();
+ clique = RecursionUtils.GetClique(5, n => s_CliqueGraph[n]).ToArray();
Assert.AreEqual(2, clique.Length);
Assert.IsTrue(clique.Contains(5));
diff --git a/ICD.Common.Utils/RecursionUtils.cs b/ICD.Common.Utils/RecursionUtils.cs
index 826f35f..ad0e857 100644
--- a/ICD.Common.Utils/RecursionUtils.cs
+++ b/ICD.Common.Utils/RecursionUtils.cs
@@ -36,14 +36,18 @@ namespace ICD.Common.Utils
/// Gets the clique containing the given node.
///
///
- ///
///
///
///
- public static IEnumerable GetClique(IEnumerable nodes, T node, Func> getAdjacent)
+ public static IEnumerable GetClique(T node, Func> getAdjacent)
{
- Dictionary> map = nodes.ToDictionary(n => n, getAdjacent);
- return GetClique(map, node);
+ if (node == null)
+ throw new ArgumentNullException("node");
+
+ if (getAdjacent == null)
+ throw new ArgumentNullException("getAdjacent");
+
+ return BreadthFirstSearch(node, getAdjacent);
}
///
@@ -163,7 +167,7 @@ namespace ICD.Common.Utils
}
///
- /// Returns all of the nodes in the tree via breadth-first search.
+ /// Returns all of the nodes in the graph via breadth-first search.
///
///
///
@@ -171,6 +175,7 @@ namespace ICD.Common.Utils
///
private static IEnumerable BreadthFirstSearchIterator(T root, Func> getChildren)
{
+ IcdHashSet visited = new IcdHashSet {root};
Queue process = new Queue();
process.Enqueue(root);
@@ -179,8 +184,11 @@ namespace ICD.Common.Utils
{
yield return current;
- foreach (T child in getChildren(current))
+ foreach (T child in getChildren(current).Where(c => !visited.Contains(c)))
+ {
+ visited.Add(child);
process.Enqueue(child);
+ }
}
}