aboutsummaryrefslogtreecommitdiffstats
path: root/libdevcore/Algorithms.h
diff options
context:
space:
mode:
Diffstat (limited to 'libdevcore/Algorithms.h')
-rw-r--r--libdevcore/Algorithms.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/libdevcore/Algorithms.h b/libdevcore/Algorithms.h
index 7fe2472d..34a4dfe5 100644
--- a/libdevcore/Algorithms.h
+++ b/libdevcore/Algorithms.h
@@ -75,4 +75,47 @@ private:
V const* m_firstCycleVertex = nullptr;
};
+/**
+ * Generic breadth first search.
+ *
+ * Example: Gather all (recursive) children in a graph starting at (and including) ``root``:
+ *
+ * Node const* root = ...;
+ * std::set<Node> allNodes = BreadthFirstSearch<Node>{{root}}.run([](Node const& _node, auto&& _addChild) {
+ * // Potentially process ``_node``.
+ * for (Node const& _child: _node.children())
+ * // Potentially filter the children to be visited.
+ * _addChild(_child);
+ * }).visited;
+ *
+ * Note that the order of the traversal is *non-deterministic* (the children are stored in a std::set of pointers).
+ */
+template<typename V>
+struct BreadthFirstSearch
+{
+ /// Runs the breadth first search. The verticesToTraverse member of the struct needs to be initialized.
+ /// @param _forEachChild is a callable of the form [...](V const& _node, auto&& _addChild) { ... }
+ /// that is called for each visited node and is supposed to call _addChild(childNode) for every child
+ /// node of _node.
+ template<typename ForEachChild>
+ BreadthFirstSearch& run(ForEachChild&& _forEachChild)
+ {
+ while (!verticesToTraverse.empty())
+ {
+ V const* v = *verticesToTraverse.begin();
+ verticesToTraverse.erase(verticesToTraverse.begin());
+ visited.insert(v);
+
+ _forEachChild(*v, [this](V const& _vertex) {
+ if (!visited.count(&_vertex))
+ verticesToTraverse.insert(&_vertex);
+ });
+ }
+ return *this;
+ }
+
+ std::set<V const*> verticesToTraverse;
+ std::set<V const*> visited{};
+};
+
}