diff --git a/src/algorithms.rs b/src/algorithms.rs index b974441..3f2aa0e 100644 --- a/src/algorithms.rs +++ b/src/algorithms.rs @@ -1,3 +1,33 @@ +//! Algorithms for graph topologies. +//! +//! # Dijkstra's algorithm +//! +//! [Dijkstra's algorithm] finds the shortest distances from a source vertex to all other vertices +//! in the graph. Note that for unweighted graphs it has worse time and space complexity than +//! [Breadth-first search](#breadth-first-search). +//! +//! Variants: [`dijkstra`], [`dijkstra_distances`], [`dijkstra_unweighted`], +//! [`dijkstra_distances_unweighted`]. +//! +//! # Breadth-first search +//! +//! [Breadth-first search] traverses a graph topology, exploring all neighboring vertices first +//! before descending further into their neighborhoods. +//! +//! Variants: [`bfs`], [`bfs_distances`], [`bfs_find`], [`bfs_find_where`] +//! +//! # Depth-first search +//! +//! [Depth-first search] traverses a graph topology, exploring each branch path as far as possible +//! first before backtracking and exploring other branches. +//! +//! Variants: [`dfs`], [`dfs_visited`], [`dfs_find`], [`dfs_find_where`], [`dfs_find_path`], +//! [`dfs_find_path_where`] +//! +//! [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search +//! [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search +//! [Dijkstra's algorithm]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + use std::cmp::Ordering; use std::collections::{BinaryHeap, VecDeque}; @@ -22,12 +52,39 @@ impl Ord for DistanceOrderedVertex { } } +/// Return data type for [`dijkstra`] and [`dijkstra unweighted`]. pub struct DijkstraResult { + /// Vertex map of minimum distances from a given `source` vertex. pub distances: VertexMap>, + + /// Vertex map of predecessors on some shortest path from a given `source` vertex. pub predecessors: VertexMap>, } // TODO: Generalize the return type of the weight function. +/// Dijkstra's algorithm with custom edge weights, returns minimum distances and predecessors. +/// +/// # Panics +/// +/// Panics if `source` is not a valid vertex of `graph`. +/// +/// # Examples +/// +/// ``` +/// # use grapherity::prelude::*; +/// # use grapherity::algorithms::dijkstra; +/// # use grapherity::models::Graph; +/// let mut graph = Graph::new(); +/// let source = graph.add_vertex(); +/// let target = graph.add_vertex(); +/// let e = graph.add_edge(source, target); +/// let mut weights = graph.edge_map(1); +/// weights[e] = 5; +/// +/// let result = dijkstra(&graph, source, |e| weights[e]); +/// assert_eq!(result.distances[target], Some(5)); +/// assert_eq!(result.predecessors[target], Some(source)); +/// ``` pub fn dijkstra(graph: &G, source: G::Vertex, weight: W) -> DijkstraResult where G: GraphTopology, @@ -43,13 +100,28 @@ where } } -pub fn dijkstra_unweighted(graph: &G, source: G::Vertex) -> DijkstraResult -where - G: GraphTopology, -{ - dijkstra(graph, source, |_| 1) -} - +/// Dijkstra's algorithm with custom edge weights, returns minimum distances. +/// +/// # Panics +/// +/// Panics if `source` is not a valid vertex of `graph`. +/// +/// # Examples +/// +/// ``` +/// # use grapherity::prelude::*; +/// # use grapherity::algorithms::{dijkstra, dijkstra_distances}; +/// # use grapherity::models::Graph; +/// let mut graph = Graph::new(); +/// let source = graph.add_vertex(); +/// let target = graph.add_vertex(); +/// let e = graph.add_edge(source, target); +/// let mut weights = graph.edge_map(1); +/// weights[e] = 5; +/// +/// let distances = dijkstra_distances(&graph, source, |e| weights[e]); +/// assert_eq!(distances[target], Some(5)); +/// ``` pub fn dijkstra_distances( graph: &G, source: G::Vertex, @@ -62,6 +134,55 @@ where dijkstra_impl(graph, source, weight, |_, _| {}) } +/// Dijkstra's algorithm with constant weights of *1* for all edges, returns minimum distances and +/// predecessors. +/// +/// # Panics +/// +/// Panics if `source` is not a valid vertex of `graph`. +/// +/// # Examples +/// +/// ``` +/// # use grapherity::prelude::*; +/// # use grapherity::algorithms::{dijkstra, dijkstra_unweighted}; +/// # use grapherity::models::Graph; +/// let mut graph = Graph::new(); +/// let source = graph.add_vertex(); +/// let target = graph.add_vertex(); +/// graph.add_edge(source, target); +/// +/// let result = dijkstra_unweighted(&graph, source); +/// assert_eq!(result.distances[target], Some(1)); +/// assert_eq!(result.predecessors[target], Some(source)); +/// ``` +pub fn dijkstra_unweighted(graph: &G, source: G::Vertex) -> DijkstraResult +where + G: GraphTopology, +{ + dijkstra(graph, source, |_| 1) +} + +/// Dijkstra's algorithm with constant weights of *1* for all edges, returns minimum distances. +/// +/// # Panics +/// +/// Panics if `source` is not a valid vertex of `graph`. +/// +/// # Examples +/// +/// ``` +/// # use grapherity::prelude::*; +/// # use grapherity::algorithms::{dijkstra, dijkstra_distances_unweighted}; +/// # use grapherity::models::Graph; +/// let mut graph = Graph::new(); +/// let source = graph.add_vertex(); +/// let target = graph.add_vertex(); +/// graph.add_edge(source, target); +/// +/// let distances = dijkstra_distances_unweighted(&graph, source); +/// assert_eq!(distances[target], Some(1)); +/// ``` pub fn dijkstra_distances_unweighted( graph: &G, source: G::Vertex,