801-prims-mst — Prim's Minimum Spanning Tree
Tutorial Video
Text description (accessibility)
This video demonstrates the "801-prims-mst — Prim's Minimum Spanning Tree" functional Rust example. Difficulty level: Fundamental. Key concepts covered: Functional Programming. A Minimum Spanning Tree (MST) of a weighted undirected graph connects all vertices with minimum total edge weight. Key difference from OCaml: 1. **Priority queue**: Rust's `BinaryHeap<Reverse<...>>` is a max
Tutorial
The Problem
A Minimum Spanning Tree (MST) of a weighted undirected graph connects all vertices with minimum total edge weight. Prim's algorithm (1957) grows the MST greedily from a starting vertex, always adding the cheapest edge connecting the MST to a new vertex. MSTs are used in network design (laying cables or pipes with minimum cost), cluster analysis, and approximation algorithms for traveling salesman.
🎯 Learning Outcomes
BinaryHeap<Reverse<(weight, vertex)>>) to always select the cheapest edgeCode Example
#![allow(clippy::all)]
//! # Prim's MST Algorithm
use std::cmp::Reverse;
use std::collections::BinaryHeap;
pub fn prims_mst(n: usize, edges: &[(usize, usize, i32)]) -> i32 {
let mut adj = vec![vec![]; n];
for &(u, v, w) in edges {
adj[u].push((v, w));
adj[v].push((u, w));
}
let mut visited = vec![false; n];
let mut heap = BinaryHeap::new();
heap.push(Reverse((0, 0)));
let mut total = 0;
while let Some(Reverse((w, u))) = heap.pop() {
if visited[u] {
continue;
}
visited[u] = true;
total += w;
for &(v, wt) in &adj[u] {
if !visited[v] {
heap.push(Reverse((wt, v)));
}
}
}
total
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prims() {
let edges = [(0, 1, 4), (0, 7, 8), (1, 2, 8), (1, 7, 11)];
assert!(prims_mst(8, &edges) > 0);
}
}Key Differences
BinaryHeap<Reverse<...>> is a max-heap turned into a min-heap via Reverse; OCaml uses Set as a BST-based priority queue.OCaml Approach
OCaml uses Map or Hashtbl for adjacency lists and Set as a priority queue (OCaml's set is a balanced BST, giving O(log n) min extraction). Alternatively, module PQueue = Set.Make(...) serves as a min-heap. The Ocamlgraph library provides Kruskal and Prim implementations. OCaml's Array.iteri can build adjacency lists from edge arrays efficiently.
Full Source
#![allow(clippy::all)]
//! # Prim's MST Algorithm
use std::cmp::Reverse;
use std::collections::BinaryHeap;
pub fn prims_mst(n: usize, edges: &[(usize, usize, i32)]) -> i32 {
let mut adj = vec![vec![]; n];
for &(u, v, w) in edges {
adj[u].push((v, w));
adj[v].push((u, w));
}
let mut visited = vec![false; n];
let mut heap = BinaryHeap::new();
heap.push(Reverse((0, 0)));
let mut total = 0;
while let Some(Reverse((w, u))) = heap.pop() {
if visited[u] {
continue;
}
visited[u] = true;
total += w;
for &(v, wt) in &adj[u] {
if !visited[v] {
heap.push(Reverse((wt, v)));
}
}
}
total
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prims() {
let edges = [(0, 1, 4), (0, 7, 8), (1, 2, 8), (1, 7, 11)];
assert!(prims_mst(8, &edges) > 0);
}
}#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prims() {
let edges = [(0, 1, 4), (0, 7, 8), (1, 2, 8), (1, 7, 11)];
assert!(prims_mst(8, &edges) > 0);
}
}
Deep Comparison
OCaml vs Rust: Prims Mst
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
(u, v, weight) triples.