Compare commits
No commits in common. "925370481cd61144072dbf9c7e2eb1e7dc2e8ed3" and "6f8783b857f7e2e44770f2817be38955da90154a" have entirely different histories.
925370481c
...
6f8783b857
@ -52,5 +52,4 @@ implementations of graph-theoretical algorithms and utilities in rust.
|
||||
|
||||
- [ ] make vertex identities separate from vertex data
|
||||
- [ ] if useful, add `(V, inc(E))` representation (incidence matrix)
|
||||
- [ ] improve allocation size heuristic for queue, visited set, etc in search algos
|
||||
|
||||
|
||||
40
src/graph.rs
40
src/graph.rs
@ -42,19 +42,20 @@ 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()
|
||||
@ -71,35 +72,4 @@ 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 ¤t = 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
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,16 +44,13 @@ fn main() {
|
||||
_ => 2,
|
||||
};
|
||||
|
||||
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 = g.find_path_bfs(a, b);
|
||||
assert!(path.is_some(), "Path from {a} to {b} should be found in G");
|
||||
|
||||
let path = path.unwrap();
|
||||
assert_eq!(
|
||||
path.len(), shortest_path_length,
|
||||
"Shortest path (bfs) from {a} to {b} in G should have length {shortest_path_length}\nFound path: {path:?}"
|
||||
"Shortest path from {a} to {b} in G should have length {shortest_path_length}\nFound path: {path:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user