From 0f7e3959f2966ddbf8207f8c8112a24bc18f8e00 Mon Sep 17 00:00:00 2001 From: mxhagen Date: Sat, 15 Feb 2025 15:10:48 +0100 Subject: [PATCH] add basic dfs --- src/graph.rs | 40 +++++++++++++++++++++++++++++++++++----- src/main.rs | 9 ++++++--- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index 45b0869..a43e081 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -42,20 +42,19 @@ where /// find a path between two nodes using breadth-first-search. /// this finds a path with the least possible edges. - pub fn find_path_bfs(&self, from: V, to: V) -> Option> { + pub fn find_path_bfs(&self, from: &V, to: &V) -> Option> { let mut q = VecDeque::with_capacity(self.vertices.len()); let mut visited = HashSet::with_capacity(self.vertices.len()); - q.push_back(vec![&from]); - visited.insert(&from); + q.push_back(vec![from]); + visited.insert(from); while !q.is_empty() { let mut path = q.pop_front().unwrap(); - path.reserve(1); let current = path.last().unwrap(); for neighbor in self.neighbors(current) { - if *neighbor == to { + if neighbor == to { return path .into_iter() .cloned() @@ -72,4 +71,35 @@ where None } + + /// find a path between two nodes using depth-first-search. + /// + /// this is short-circuiting and therefore does not guarantee + /// the found path to contain the least possible edges. + pub fn find_path_dfs(&self, from: &V, to: &V) -> Option> { + let mut q = Vec::with_capacity(self.vertices.len()); + + q.push(vec![from]); + + while !q.is_empty() { + let mut path = q.pop().unwrap(); + let ¤t = path.last().unwrap(); + + if current == to { + return path.into_iter().cloned().collect::>().into(); + } + + for neighbor in self.neighbors(current).iter().rev() { + if path.contains(&neighbor) { + continue; + } + + path.push(neighbor); + q.push(path.clone()); + path.pop(); + } + } + + None + } } diff --git a/src/main.rs b/src/main.rs index c52e279..47e65a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,13 +44,16 @@ fn main() { _ => 2, }; - let path = g.find_path_bfs(a, b); - assert!(path.is_some(), "Path from {a} to {b} should be found in G"); + let path = g.find_path_dfs(&a, &b); + assert!(path.is_some(), "Path from {a} to {b} should be found in G with dfs"); + + let path = g.find_path_bfs(&a, &b); + assert!(path.is_some(), "Path from {a} to {b} should be found in G with bfs"); let path = path.unwrap(); assert_eq!( path.len(), shortest_path_length, - "Shortest path from {a} to {b} in G should have length {shortest_path_length}\nFound path: {path:?}" + "Shortest path (bfs) from {a} to {b} in G should have length {shortest_path_length}\nFound path: {path:?}" ); } }