Add "algorithms" and "models" modules for existing code and related todos
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
use crate::models::Graph;
|
||||
use crate::models::Vertex;
|
||||
|
||||
#[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?
|
||||
// TODO: Maybe variant of Dijkstra's algorithm without predecessors?
|
||||
pub 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)
|
||||
}
|
||||
Reference in New Issue
Block a user