added dijkstras with test pass
This commit is contained in:
parent
fc92909aec
commit
4a53a4cac5
1 changed files with 97 additions and 40 deletions
137
src/dijkstras.rs
137
src/dijkstras.rs
|
|
@ -1,42 +1,46 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::dijkstras_shortest_path;
|
||||
use super::{dijkstras_shortest_path,WeightedAdjacencyList};
|
||||
#[test]
|
||||
fn dijkstras_shortest_path_primeagen_class_test(){
|
||||
// (B) --- (E) ---- (F)
|
||||
// (1) --- (4) ---- (5)
|
||||
// / | | /|
|
||||
// (A) | ------|------- |
|
||||
// (0) | ------|------- |
|
||||
// \ |/ | |
|
||||
// (C) --- (D) ---- (G)
|
||||
let mut graph:WeightedAdjacencyList<&str,usize> = WeightedAdjacencyList::new();
|
||||
graph.add_vertex("A");
|
||||
graph.add_vertex("B");
|
||||
graph.add_vertex("C");
|
||||
graph.add_vertex("D");
|
||||
graph.add_vertex("E");
|
||||
graph.add_vertex("F");
|
||||
graph.add_edge("A","B",3);
|
||||
graph.add_edge("A","C",1);
|
||||
graph.add_edge("B","A",3);
|
||||
graph.add_edge("B","C",4);
|
||||
graph.add_edge("B","E",1);
|
||||
graph.add_edge("C","B",4);
|
||||
graph.add_edge("C","D",7);
|
||||
graph.add_edge("C","A",1);
|
||||
graph.add_edge("D","C",7);
|
||||
graph.add_edge("D","E",5);
|
||||
graph.add_edge("D","G",1);
|
||||
graph.add_edge("E","B",1);
|
||||
graph.add_edge("E","D",5);
|
||||
graph.add_edge("E","F",2);
|
||||
graph.add_edge("F","G",1);
|
||||
graph.add_edge("F","E",2);
|
||||
graph.add_edge("F","C",18);
|
||||
graph.add_edge("G","D",1);
|
||||
graph.add_edge("G","F",1);
|
||||
dijkstras_shortest_path(source,sink,graph);
|
||||
// (2) --- (3) ---- (6)
|
||||
let source = 0;
|
||||
let sink = 5;
|
||||
|
||||
let mut graph:WeightedAdjacencyList<usize,usize> = WeightedAdjacencyList::new();
|
||||
graph.add_vertex(0);
|
||||
graph.add_vertex(1);
|
||||
graph.add_vertex(2);
|
||||
graph.add_vertex(3);
|
||||
graph.add_vertex(4);
|
||||
graph.add_vertex(5);
|
||||
graph.add_edge(0, 1, 3);
|
||||
graph.add_edge(0, 2, 1);
|
||||
graph.add_edge(1, 0, 3);
|
||||
graph.add_edge(1, 2, 4);
|
||||
graph.add_edge(1, 4, 1);
|
||||
graph.add_edge(2, 1, 4);
|
||||
graph.add_edge(2, 3, 7);
|
||||
graph.add_edge(2, 0, 1);
|
||||
graph.add_edge(3, 2, 7);
|
||||
graph.add_edge(3, 4, 5);
|
||||
graph.add_edge(3, 6, 1);
|
||||
graph.add_edge(4, 1, 1);
|
||||
graph.add_edge(4, 3, 5);
|
||||
graph.add_edge(4, 5, 2);
|
||||
graph.add_edge(5, 6, 1);
|
||||
graph.add_edge(5, 4, 2);
|
||||
graph.add_edge(5, 2, 18);
|
||||
graph.add_edge(6, 3, 1);
|
||||
graph.add_edge(6, 5, 1);
|
||||
let path = dijkstras_shortest_path(source,sink,graph.clone());
|
||||
assert_eq!(path.unwrap(), vec![0, 1, 4, 5]);
|
||||
}
|
||||
}
|
||||
// Define a struct to represent the adjacency list with weighted edges
|
||||
|
|
@ -44,6 +48,18 @@ pub struct WeightedAdjacencyList<T, W> {
|
|||
vertices: HashMap<T, HashMap<T, W>>,
|
||||
}
|
||||
|
||||
impl<T, W> Clone for WeightedAdjacencyList<T, W>
|
||||
where
|
||||
T: Clone,
|
||||
W: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
WeightedAdjacencyList {
|
||||
vertices: self.vertices.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, W> WeightedAdjacencyList<T, W>
|
||||
where
|
||||
T: std::hash::Hash + Eq + Clone,
|
||||
|
|
@ -79,24 +95,65 @@ where
|
|||
fn get_neighbors(&self, vertex: &T) -> Option<&HashMap<T, W>> {
|
||||
self.vertices.get(vertex)
|
||||
}
|
||||
// Method to get the number of vertices in the adjacency list
|
||||
fn len(&self) -> usize {
|
||||
self.vertices.len()
|
||||
}
|
||||
}
|
||||
pub fn dijkstras_shortest_path(
|
||||
source: usize,
|
||||
sink: usize,
|
||||
graph: WeightedAdjacencyList<usize, usize>,
|
||||
) -> Option<Vec<usize>> {
|
||||
let mut seen: Vec<bool> = vec![false; graph.len()];
|
||||
let mut prev: Vec<usize> = vec![usize::MAX; graph.len()];
|
||||
let mut dists: Vec<f64> = vec![f64::INFINITY; graph.len()];
|
||||
dists[source] = 0.0;
|
||||
|
||||
while has_unvisited(&seen, &dists) {
|
||||
let curr = get_lowest_unvisited(&seen, &dists);
|
||||
seen[curr] = true;
|
||||
if let Some(adjs) = graph.get_neighbors(&curr) {
|
||||
for (&to, &weight) in adjs.iter() {
|
||||
if !seen[to] {
|
||||
let new_dist = dists[curr] + weight as f64;
|
||||
if new_dist < dists[to] {
|
||||
dists[to] = new_dist;
|
||||
prev[to] = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if sink is unreachable
|
||||
if prev[sink] == usize::MAX {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Reconstruct shortest path
|
||||
let mut path = Vec::new();
|
||||
let mut curr = sink;
|
||||
while curr != usize::MAX {
|
||||
path.push(curr);
|
||||
curr = prev[curr];
|
||||
}
|
||||
path.reverse();
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn has_unvisited(seen: &[bool], dists: &[f64]) -> bool {
|
||||
return seen.iter().enumerate().any(|(i, &s)| !s && dists[i] < f64::INFINITY);
|
||||
seen.iter().enumerate().any(|(i, &s)| !s && dists[i] < f64::INFINITY)
|
||||
}
|
||||
|
||||
fn get_lowest_unvisited(seen: &[bool], dists: &[f64]) -> usize {
|
||||
let mut idx = usize::MAX;
|
||||
let mut lowest_distance = f64::INFINITY;
|
||||
for (i, &is_seen) in seen.iter().enumerate() {
|
||||
if is_seen {
|
||||
continue;
|
||||
}
|
||||
if lowest_distance > dists[i] {
|
||||
if !is_seen && dists[i] < lowest_distance {
|
||||
lowest_distance = dists[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
idx
|
||||
}
|
||||
pub fn dijkstras_shortest_path(source:usize,sink:usize,mut graph:WeightedAdjacencyList<&str,usize>){
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue