Update Dijkstra's algorithm to use VertexMap
This commit is contained in:
+18
-17
@@ -1,6 +1,7 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
use crate::maps::VertexMap;
|
||||
use crate::traits::GraphTopology;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
@@ -21,19 +22,18 @@ impl<V: Eq> Ord for DistanceOrderedVertex<V> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DijkstraResult<V> {
|
||||
pub distances: Vec<Option<u32>>,
|
||||
pub predecessors: Vec<Option<V>>,
|
||||
pub struct DijkstraResult<V: Copy> {
|
||||
pub distances: VertexMap<V, Option<u32>>,
|
||||
pub predecessors: VertexMap<V, Option<V>>,
|
||||
}
|
||||
|
||||
pub fn dijkstra<G>(graph: &G, source: G::Vertex) -> DijkstraResult<G::Vertex>
|
||||
where
|
||||
G: GraphTopology,
|
||||
G::Vertex: Into<usize>,
|
||||
{
|
||||
let mut predecessors = vec![None; graph.vertex_count()];
|
||||
let mut predecessors = graph.vertex_map(None);
|
||||
let distances = dijkstra_impl(graph, source, |neighbor, predecessor| {
|
||||
predecessors[neighbor.into()] = Some(predecessor);
|
||||
predecessors[neighbor] = Some(predecessor);
|
||||
});
|
||||
DijkstraResult {
|
||||
distances,
|
||||
@@ -41,25 +41,27 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dijkstra_distances<G>(graph: &G, source: G::Vertex) -> Vec<Option<u32>>
|
||||
pub fn dijkstra_distances<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, Option<u32>>
|
||||
where
|
||||
G: GraphTopology,
|
||||
G::Vertex: Into<usize>,
|
||||
{
|
||||
dijkstra_impl(graph, source, |_, _| {})
|
||||
}
|
||||
|
||||
// TODO: Replace Vec storage with VertexMap, this should make the bound on G::Vertex here obsolete.
|
||||
fn dijkstra_impl<G, F>(graph: &G, source: G::Vertex, mut on_relax: F) -> Vec<Option<u32>>
|
||||
// TODO: Add a way to provide custom edge weights for Dijkstra's algorithm.
|
||||
fn dijkstra_impl<G, F>(
|
||||
graph: &G,
|
||||
source: G::Vertex,
|
||||
mut on_relax: F,
|
||||
) -> VertexMap<G::Vertex, Option<u32>>
|
||||
where
|
||||
G: GraphTopology,
|
||||
G::Vertex: Into<usize>,
|
||||
F: FnMut(G::Vertex, G::Vertex),
|
||||
{
|
||||
let mut distances = vec![None; graph.vertex_count()];
|
||||
let mut distances = graph.vertex_map(None);
|
||||
let mut heap = BinaryHeap::new();
|
||||
|
||||
distances[source.into()] = Some(0);
|
||||
distances[source] = Some(0);
|
||||
heap.push(DistanceOrderedVertex {
|
||||
vertex: source,
|
||||
distance: 0,
|
||||
@@ -67,15 +69,14 @@ where
|
||||
|
||||
while let Some(v) = heap.pop() {
|
||||
for neighbor in graph.neighbors(v.vertex) {
|
||||
// TODO: Add a way to provide custom edge weights for Dijkstra's algorithm.
|
||||
let edge_weight = 1;
|
||||
let new_distance = distances[v.vertex.into()].unwrap() + edge_weight;
|
||||
if match distances[neighbor.into()] {
|
||||
let new_distance = distances[v.vertex].unwrap() + edge_weight;
|
||||
if match distances[neighbor] {
|
||||
None => true,
|
||||
Some(old_distance) if old_distance > new_distance => true,
|
||||
_ => false,
|
||||
} {
|
||||
distances[neighbor.into()] = Some(new_distance);
|
||||
distances[neighbor] = Some(new_distance);
|
||||
on_relax(neighbor, v.vertex);
|
||||
heap.push(DistanceOrderedVertex {
|
||||
vertex: neighbor,
|
||||
|
||||
Reference in New Issue
Block a user