add basic dfs

This commit is contained in:
mxhagen 2025-02-15 15:10:48 +01:00
parent 6f8783b857
commit 0f7e3959f2
2 changed files with 41 additions and 8 deletions

View File

@ -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<Vec<V>> {
pub fn find_path_bfs(&self, from: &V, to: &V) -> Option<Vec<V>> {
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<Vec<V>> {
let mut q = Vec::with_capacity(self.vertices.len());
q.push(vec![from]);
while !q.is_empty() {
let mut path = q.pop().unwrap();
let &current = path.last().unwrap();
if current == to {
return path.into_iter().cloned().collect::<Vec<_>>().into();
}
for neighbor in self.neighbors(current).iter().rev() {
if path.contains(&neighbor) {
continue;
}
path.push(neighbor);
q.push(path.clone());
path.pop();
}
}
None
}
}

View File

@ -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:?}"
);
}
}