Add depth-first search algorithms and tests

This commit is contained in:
2026-06-26 15:34:42 +02:00
parent 91ac925417
commit 135f256141
4 changed files with 289 additions and 0 deletions
+74
View File
@@ -186,3 +186,77 @@ where
}
(distances, None)
}
pub struct DfsResult<V: Copy> {
pub visited: VertexMap<V, bool>,
pub predecessors: VertexMap<V, Option<V>>,
}
pub fn dfs<G>(graph: &G, source: G::Vertex) -> DfsResult<G::Vertex>
where
G: GraphTopology,
{
let mut predecessors = graph.vertex_map(None);
let (visited, _) = dfs_impl(graph, source, |neighbor, predecessor| {
predecessors[neighbor] = Some(predecessor);
true
});
DfsResult {
visited,
predecessors,
}
}
pub fn dfs_visited<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, bool>
where
G: GraphTopology,
{
dfs_impl(graph, source, |_, _| true).0
}
pub fn dfs_find<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> bool
where
G: GraphTopology,
{
dfs_find_where(graph, source, |v| v == target).is_some()
}
pub fn dfs_find_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<G::Vertex>
where
G: GraphTopology,
P: Fn(G::Vertex) -> bool,
{
if predicate(source) {
return Some(source);
}
dfs_impl(graph, source, |neighbor, _| !predicate(neighbor)).1
}
fn dfs_impl<G, F>(
graph: &G,
source: G::Vertex,
mut on_discover: F,
) -> (VertexMap<G::Vertex, bool>, Option<G::Vertex>)
where
G: GraphTopology,
F: FnMut(G::Vertex, G::Vertex) -> bool,
{
let mut visited = graph.vertex_map(false);
visited[source] = true;
let mut stack = vec![(source, None::<G::Vertex>)];
while let Some((v, predecessor)) = stack.pop() {
if let Some(p) = predecessor {
if !on_discover(v, p) {
return (visited, Some(v));
}
}
for neighbor in graph.adjacent_vertices(v) {
if !visited[neighbor] {
visited[neighbor] = true;
stack.push((neighbor, Some(v)));
}
}
}
(visited, None)
}