From 912861452c7022dbb1bbe904a8a958b0b8507162 Mon Sep 17 00:00:00 2001 From: yut23 Date: Fri, 26 Jan 2024 16:52:12 -0500 Subject: [PATCH] 2023: switch dfs to be non-recursive The perf stack traces for the recursive version were absolutely awful. --- 2023/src/graph_traversal.hpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/2023/src/graph_traversal.hpp b/2023/src/graph_traversal.hpp index c00a328..bebbf75 100644 --- a/2023/src/graph_traversal.hpp +++ b/2023/src/graph_traversal.hpp @@ -11,7 +11,7 @@ #define GRAPH_TRAVERSAL_HPP_56T9ZURK #include "util/concepts.hpp" -#include // for reverse +#include // for min, reverse #include // for same_as, integral #include // for function, greater #include // for map @@ -19,6 +19,7 @@ #include // for set #include // for stack #include // for invalid_argument +#include // for tuple #include // for conditional_t // IWYU pragma: export #include // for unordered_map #include // for unordered_set @@ -165,20 +166,19 @@ template VisitWithParent> int dfs(const Key &source, GetNeighbors &&get_neighbors, IsTarget &&is_target, VisitWithParent &&visit_with_parent) { + std::stack> stack{}; + stack.emplace(source, source, 0); detail::maybe_unordered_set seen{}; - auto helper = [&seen, &get_neighbors, &is_target, - &visit_with_parent](const Key &key, int depth, - const Key &parent, const auto &rec) { + while (!stack.empty()) { + const auto [key, parent, depth] = std::move(stack.top()); + stack.pop(); visit_with_parent(key, parent, depth); if (is_target(key)) { - return depth; + return stack.size() - 1; } if constexpr (use_seen) { seen.insert(key); - } else { - // suppress unused lambda capture warning - (void)seen; } for (const Key &neighbor : get_neighbors(key)) { if constexpr (use_seen) { @@ -186,15 +186,10 @@ int dfs(const Key &source, GetNeighbors &&get_neighbors, IsTarget &&is_target, continue; } } - int result = rec(neighbor, depth + 1, key, rec); - if (result != -1) { - return result; - } + stack.emplace(neighbor, key, depth + 1); } - return -1; - }; - - return helper(source, 0, source, helper); + } + return -1; } template