mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-01-11 13:19: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