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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::dijkstras_shortest_path;
|
use super::{dijkstras_shortest_path,WeightedAdjacencyList};
|
||||||
#[test]
|
#[test]
|
||||||
fn dijkstras_shortest_path_primeagen_class_test(){
|
fn dijkstras_shortest_path_primeagen_class_test(){
|
||||||
// (B) --- (E) ---- (F)
|
// (1) --- (4) ---- (5)
|
||||||
// / | | /|
|
// / | | /|
|
||||||
// (A) | ------|------- |
|
// (0) | ------|------- |
|
||||||
// \ |/ | |
|
// \ |/ | |
|
||||||
// (C) --- (D) ---- (G)
|
// (2) --- (3) ---- (6)
|
||||||
let mut graph:WeightedAdjacencyList<&str,usize> = WeightedAdjacencyList::new();
|
let source = 0;
|
||||||
graph.add_vertex("A");
|
let sink = 5;
|
||||||
graph.add_vertex("B");
|
|
||||||
graph.add_vertex("C");
|
let mut graph:WeightedAdjacencyList<usize,usize> = WeightedAdjacencyList::new();
|
||||||
graph.add_vertex("D");
|
graph.add_vertex(0);
|
||||||
graph.add_vertex("E");
|
graph.add_vertex(1);
|
||||||
graph.add_vertex("F");
|
graph.add_vertex(2);
|
||||||
graph.add_edge("A","B",3);
|
graph.add_vertex(3);
|
||||||
graph.add_edge("A","C",1);
|
graph.add_vertex(4);
|
||||||
graph.add_edge("B","A",3);
|
graph.add_vertex(5);
|
||||||
graph.add_edge("B","C",4);
|
graph.add_edge(0, 1, 3);
|
||||||
graph.add_edge("B","E",1);
|
graph.add_edge(0, 2, 1);
|
||||||
graph.add_edge("C","B",4);
|
graph.add_edge(1, 0, 3);
|
||||||
graph.add_edge("C","D",7);
|
graph.add_edge(1, 2, 4);
|
||||||
graph.add_edge("C","A",1);
|
graph.add_edge(1, 4, 1);
|
||||||
graph.add_edge("D","C",7);
|
graph.add_edge(2, 1, 4);
|
||||||
graph.add_edge("D","E",5);
|
graph.add_edge(2, 3, 7);
|
||||||
graph.add_edge("D","G",1);
|
graph.add_edge(2, 0, 1);
|
||||||
graph.add_edge("E","B",1);
|
graph.add_edge(3, 2, 7);
|
||||||
graph.add_edge("E","D",5);
|
graph.add_edge(3, 4, 5);
|
||||||
graph.add_edge("E","F",2);
|
graph.add_edge(3, 6, 1);
|
||||||
graph.add_edge("F","G",1);
|
graph.add_edge(4, 1, 1);
|
||||||
graph.add_edge("F","E",2);
|
graph.add_edge(4, 3, 5);
|
||||||
graph.add_edge("F","C",18);
|
graph.add_edge(4, 5, 2);
|
||||||
graph.add_edge("G","D",1);
|
graph.add_edge(5, 6, 1);
|
||||||
graph.add_edge("G","F",1);
|
graph.add_edge(5, 4, 2);
|
||||||
dijkstras_shortest_path(source,sink,graph);
|
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
|
// 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>>,
|
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>
|
impl<T, W> WeightedAdjacencyList<T, W>
|
||||||
where
|
where
|
||||||
T: std::hash::Hash + Eq + Clone,
|
T: std::hash::Hash + Eq + Clone,
|
||||||
|
|
@ -79,24 +95,65 @@ where
|
||||||
fn get_neighbors(&self, vertex: &T) -> Option<&HashMap<T, W>> {
|
fn get_neighbors(&self, vertex: &T) -> Option<&HashMap<T, W>> {
|
||||||
self.vertices.get(vertex)
|
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 {
|
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 {
|
fn get_lowest_unvisited(seen: &[bool], dists: &[f64]) -> usize {
|
||||||
let mut idx = usize::MAX;
|
let mut idx = usize::MAX;
|
||||||
let mut lowest_distance = f64::INFINITY;
|
let mut lowest_distance = f64::INFINITY;
|
||||||
for (i, &is_seen) in seen.iter().enumerate() {
|
for (i, &is_seen) in seen.iter().enumerate() {
|
||||||
if is_seen {
|
if !is_seen && dists[i] < lowest_distance {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if lowest_distance > dists[i] {
|
|
||||||
lowest_distance = dists[i];
|
lowest_distance = dists[i];
|
||||||
idx = i;
|
idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx
|
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