mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-01-11 21:29:18 +00:00
Added dikjstra algorithm
This commit is contained in:
parent
c5898ac6b7
commit
140bc616e9
1
exercises/Algorithms/Dijkstra Algorithm/.gitignore
vendored
Normal file
1
exercises/Algorithms/Dijkstra Algorithm/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
7
exercises/Algorithms/Dijkstra Algorithm/Cargo.lock
generated
Normal file
7
exercises/Algorithms/Dijkstra Algorithm/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "graph-in-rust"
|
||||||
|
version = "0.1.0"
|
||||||
8
exercises/Algorithms/Dijkstra Algorithm/Cargo.toml
Normal file
8
exercises/Algorithms/Dijkstra Algorithm/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "graph-in-rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
5
exercises/Algorithms/Dijkstra Algorithm/readme.md
Normal file
5
exercises/Algorithms/Dijkstra Algorithm/readme.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
## Dijsktra Algorithm in Rust
|
||||||
|
|
||||||
|
The `src` directory consist of 2 files: `main.rs` and `graph.in`. The `graph.in` file consist of a `vec![]` which is a `vector` of data as: `(source, destination, cost)`. This graph is comprised of `6` nodes and their `cost`.
|
||||||
|
|
||||||
|
The algorithm returns the shortest path between 2 nodes. The function `shortest_path(g: &Graph, start: Node, goal: Node)` takes start and end nodes and returns the total cost to reach the goal.
|
||||||
9
exercises/Algorithms/Dijkstra Algorithm/src/graph.in
Normal file
9
exercises/Algorithms/Dijkstra Algorithm/src/graph.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
vec![
|
||||||
|
(0, 1, 5),
|
||||||
|
(0, 2, 10),
|
||||||
|
(1, 2, 7),
|
||||||
|
(1, 4, 3),
|
||||||
|
(2, 4, 5),
|
||||||
|
(4, 5, 10),
|
||||||
|
(5, 6, 7)
|
||||||
|
]
|
||||||
131
exercises/Algorithms/Dijkstra Algorithm/src/main.rs
Normal file
131
exercises/Algorithms/Dijkstra Algorithm/src/main.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::{BinaryHeap, HashMap, HashSet};
|
||||||
|
type Node = usize;
|
||||||
|
type Cost = usize;
|
||||||
|
|
||||||
|
struct Graph {
|
||||||
|
edges: HashMap<Node, Vec<(Node, Cost)>>,
|
||||||
|
nodes: HashSet<Node>,
|
||||||
|
}
|
||||||
|
#[warn(clippy::redundant_closure)]
|
||||||
|
impl Graph {
|
||||||
|
fn from_edge_list(edge_list: &[(Node, Node, Cost)]) -> Self {
|
||||||
|
let mut adjacency_list: HashMap<Node, Vec<(Node, Cost)>> = HashMap::new();
|
||||||
|
let mut nodes = HashSet::new();
|
||||||
|
|
||||||
|
for &(source, destination, cost) in edge_list.iter() {
|
||||||
|
let destinations = adjacency_list.entry(source).or_insert_with(|| Vec::new());
|
||||||
|
|
||||||
|
destinations.push((destination, cost));
|
||||||
|
nodes.insert(source);
|
||||||
|
nodes.insert(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph {
|
||||||
|
edges: adjacency_list,
|
||||||
|
nodes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq)]
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
struct Curr {
|
||||||
|
cost: Cost,
|
||||||
|
position: Node,
|
||||||
|
path: Vec<Node>,
|
||||||
|
}
|
||||||
|
impl Curr {
|
||||||
|
fn new(position: Node, cost: Cost, path: Vec<Node>) -> Self {
|
||||||
|
Curr {
|
||||||
|
cost,
|
||||||
|
position,
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn new_start(start: Node) -> Self {
|
||||||
|
Curr {
|
||||||
|
cost: 0,
|
||||||
|
position: start,
|
||||||
|
path: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Ord for Curr {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
other
|
||||||
|
.cost
|
||||||
|
.cmp(&self.cost)
|
||||||
|
.then_with(|| self.position.cmp(&other.position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Curr {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shortest_path(g: &Graph, start: Node, goal: Node) -> Option<(Vec<Node>, Cost)> {
|
||||||
|
let mut priority_queue = BinaryHeap::new();
|
||||||
|
priority_queue.push(Curr::new_start(start));
|
||||||
|
|
||||||
|
let mut dist: HashMap<Node, Cost> = g
|
||||||
|
.nodes
|
||||||
|
.iter()
|
||||||
|
.map(|&x| if x == start { (x, 0) } else { (x, usize::MAX) })
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
while let Some(Curr {
|
||||||
|
cost,
|
||||||
|
position,
|
||||||
|
mut path,
|
||||||
|
}) = priority_queue.pop()
|
||||||
|
{
|
||||||
|
if position == goal {
|
||||||
|
path.push(position);
|
||||||
|
return Some((path, cost));
|
||||||
|
}
|
||||||
|
|
||||||
|
// pq. push (cost+ currcost, start->next, path.add(start) )
|
||||||
|
// So iterate, through all the nodes of start node which are in g
|
||||||
|
// g[start]= Vec[node, cost]
|
||||||
|
|
||||||
|
if let Some(connected_nodes) = &g.edges.get(&position) {
|
||||||
|
for &(next_node, next_cost) in connected_nodes.iter() {
|
||||||
|
if next_cost < dist[&next_node] {
|
||||||
|
let mut next = Curr::new(next_node, cost + next_cost, path.clone());
|
||||||
|
next.path.push(position);
|
||||||
|
priority_queue.push(next);
|
||||||
|
|
||||||
|
if let Some(past_cost) = dist.get_mut(&next_node) {
|
||||||
|
*past_cost = next_cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let edge_list = include!("graph.in");
|
||||||
|
let g = Graph::from_edge_list(&edge_list);
|
||||||
|
|
||||||
|
if let Some((path, cost)) = shortest_path(&g, 1, 6) {
|
||||||
|
println!("Shortest distance from 1 to 6 is: , {path:?} {cost}");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn large_graph() {
|
||||||
|
let edge_list = include!("graph.in");
|
||||||
|
let g = Graph::from_edge_list(&edge_list);
|
||||||
|
|
||||||
|
let path = shortest_path(&g, 1, 6);
|
||||||
|
assert!(path.is_some());
|
||||||
|
assert_eq!(path.unwrap().1, 20);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user