Initial release #1
+115
-2
@@ -1,3 +1,6 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::BinaryHeap;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
struct Vertex(usize);
|
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() {
|
fn main() {
|
||||||
// TODO: Move this graph example into one or more tests.
|
// TODO: Move this graph example into one or more tests.
|
||||||
let mut graph = Graph {
|
let mut graph = Graph {
|
||||||
@@ -154,6 +221,52 @@ fn main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test Dijkstra's algorithm starting at 0 and at another vertex.
|
let (distances, predecessors) = dijkstra(&graph, vertices[0]);
|
||||||
let expected_distances_to_v0 = [0, 1, 2, 2, 2, 3, 3, 3, 3, 4];
|
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