Compare commits
2 Commits
6f8783b857
...
925370481c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
925370481c | ||
|
|
0f7e3959f2 |
@ -52,4 +52,5 @@ implementations of graph-theoretical algorithms and utilities in rust.
|
|||||||
|
|
||||||
- [ ] make vertex identities separate from vertex data
|
- [ ] make vertex identities separate from vertex data
|
||||||
- [ ] if useful, add `(V, inc(E))` representation (incidence matrix)
|
- [ ] 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,20 +42,19 @@ where
|
|||||||
|
|
||||||
/// find a path between two nodes using breadth-first-search.
|
/// find a path between two nodes using breadth-first-search.
|
||||||
/// this finds a path with the least possible edges.
|
/// 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 q = VecDeque::with_capacity(self.vertices.len());
|
||||||
let mut visited = HashSet::with_capacity(self.vertices.len());
|
let mut visited = HashSet::with_capacity(self.vertices.len());
|
||||||
|
|
||||||
q.push_back(vec![&from]);
|
q.push_back(vec![from]);
|
||||||
visited.insert(&from);
|
visited.insert(from);
|
||||||
|
|
||||||
while !q.is_empty() {
|
while !q.is_empty() {
|
||||||
let mut path = q.pop_front().unwrap();
|
let mut path = q.pop_front().unwrap();
|
||||||
path.reserve(1);
|
|
||||||
let current = path.last().unwrap();
|
let current = path.last().unwrap();
|
||||||
|
|
||||||
for neighbor in self.neighbors(current) {
|
for neighbor in self.neighbors(current) {
|
||||||
if *neighbor == to {
|
if neighbor == to {
|
||||||
return path
|
return path
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
@ -72,4 +71,35 @@ where
|
|||||||
|
|
||||||
None
|
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,13 +44,16 @@ fn main() {
|
|||||||
_ => 2,
|
_ => 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = g.find_path_bfs(a, b);
|
let path = g.find_path_dfs(&a, &b);
|
||||||
assert!(path.is_some(), "Path from {a} to {b} should be found in G");
|
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();
|
let path = path.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
path.len(), shortest_path_length,
|
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:?}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user