Initial release #1
+115
-2
@@ -1,3 +1,6 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct Vertex(usize);
|
||||
|
||||
@@ -74,6 +77,70 @@ impl Graph {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct DistanceOrderedVertex {
|
||||
distance: u32,
|
||||
vertex: Vertex,
|
||||
}
|
||||
|
||||
impl PartialOrd for DistanceOrderedVertex {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.distance.cmp(&other.distance))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for DistanceOrderedVertex {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
other.distance.cmp(&self.distance)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Maybe introduce a return struct type for Dijkstra's algorithm?
|
||||
fn dijkstra(graph: &Graph, source: Vertex) -> (Vec<Option<u32>>, Vec<Option<Vertex>>) {
|
||||
let mut distances = vec![None; graph.vertex_count()];
|
||||
let mut predecessors = vec![None; graph.vertex_count()];
|
||||
let mut heap = BinaryHeap::new();
|
||||
|
||||
distances[source.0] = Some(0);
|
||||
heap.push(DistanceOrderedVertex {
|
||||
vertex: source,
|
||||
distance: 0,
|
||||
});
|
||||
while let Some(v) = heap.pop() {
|
||||
// TODO: Simplify with a neighbor iterator.
|
||||
// Finds the first neighbor of v.
|
||||
let Some(mut incidence) = graph.incidence_headers[v.vertex.0].first_incidence else {
|
||||
break;
|
||||
};
|
||||
loop {
|
||||
// Processes one neighbor of v.
|
||||
let neighbor = graph.incidence_vertices[incidence.0];
|
||||
// TODO: Add a way to provide custom edge weights for Dijkstra's algorithm.
|
||||
let edge_weight = 1;
|
||||
let new_distance = distances[v.vertex.0].unwrap() + edge_weight;
|
||||
if match distances[neighbor.0] {
|
||||
None => true,
|
||||
Some(old_distance) if old_distance > new_distance => true,
|
||||
_ => false,
|
||||
} {
|
||||
distances[neighbor.0] = Some(new_distance);
|
||||
predecessors[neighbor.0] = Some(v.vertex);
|
||||
heap.push(DistanceOrderedVertex {
|
||||
vertex: neighbor,
|
||||
distance: new_distance,
|
||||
});
|
||||
}
|
||||
|
||||
// Finds next neighbor of v.
|
||||
let Some(next) = graph.next_incidences[incidence.0] else {
|
||||
break;
|
||||
};
|
||||
incidence = next;
|
||||
}
|
||||
}
|
||||
(distances, predecessors)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// TODO: Move this graph example into one or more tests.
|
||||
let mut graph = Graph {
|
||||
@@ -154,6 +221,52 @@ fn main() {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: test Dijkstra's algorithm starting at 0 and at another vertex.
|
||||
let expected_distances_to_v0 = [0, 1, 2, 2, 2, 3, 3, 3, 3, 4];
|
||||
let (distances, predecessors) = dijkstra(&graph, vertices[0]);
|
||||
let expected_distances_from_v0 = [
|
||||
Some(0),
|
||||
Some(1),
|
||||
Some(2),
|
||||
Some(2),
|
||||
Some(2),
|
||||
Some(3),
|
||||
Some(3),
|
||||
Some(3),
|
||||
Some(3),
|
||||
Some(4),
|
||||
];
|
||||
let expected_predecessors_from_v0 = [
|
||||
vec![None],
|
||||
vec![Some(vertices[0])],
|
||||
vec![Some(vertices[1])],
|
||||
vec![Some(vertices[1])],
|
||||
vec![Some(vertices[1])],
|
||||
vec![Some(vertices[2])],
|
||||
vec![Some(vertices[2]), Some(vertices[3])],
|
||||
vec![Some(vertices[4])],
|
||||
vec![Some(vertices[4])],
|
||||
vec![Some(vertices[5]), Some(vertices[6]), Some(vertices[7])],
|
||||
];
|
||||
assert_eq!(
|
||||
distances.len(),
|
||||
graph.vertex_count(),
|
||||
"distances count from Dijkstra's algorithm must equal vertex count"
|
||||
);
|
||||
assert_eq!(
|
||||
predecessors.len(),
|
||||
graph.vertex_count(),
|
||||
"predecessors count from Dijkstra's algorithm must equal vertex count"
|
||||
);
|
||||
for i in 0..graph.vertex_count() {
|
||||
assert_eq!(
|
||||
distances[i], expected_distances_from_v0[i],
|
||||
"unexpected distance from {:?} to {:?} from Dijkstra's algorithm",
|
||||
vertices[0], vertices[i]
|
||||
);
|
||||
assert!(
|
||||
expected_predecessors_from_v0[i].contains(&predecessors[i]),
|
||||
"unexpected predecessor {:?} of {:?} from Dijkstra's algorithm",
|
||||
predecessors[i],
|
||||
vertices[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user