Add remaining docs for algorithms module
This commit is contained in:
+330
-12
@@ -14,7 +14,7 @@
|
|||||||
//! [Breadth-first search] traverses a graph topology, exploring all neighboring vertices first
|
//! [Breadth-first search] traverses a graph topology, exploring all neighboring vertices first
|
||||||
//! before descending further into their neighborhoods.
|
//! before descending further into their neighborhoods.
|
||||||
//!
|
//!
|
||||||
//! Variants: [`bfs`], [`bfs_distances`], [`bfs_find`], [`bfs_find_where`]
|
//! Variants: [`bfs`], [`bfs_distances`], [`bfs_find`], [`bfs_find_where`].
|
||||||
//!
|
//!
|
||||||
//! # Depth-first search
|
//! # Depth-first search
|
||||||
//!
|
//!
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
//! first before backtracking and exploring other branches.
|
//! first before backtracking and exploring other branches.
|
||||||
//!
|
//!
|
||||||
//! Variants: [`dfs`], [`dfs_visited`], [`dfs_find`], [`dfs_find_where`], [`dfs_find_path`],
|
//! Variants: [`dfs`], [`dfs_visited`], [`dfs_find`], [`dfs_find_where`], [`dfs_find_path`],
|
||||||
//! [`dfs_find_path_where`]
|
//! [`dfs_find_path_where`].
|
||||||
//!
|
//!
|
||||||
//! [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search
|
//! [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
//! [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
//! [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
@@ -52,17 +52,21 @@ impl<V: Eq> Ord for DistanceOrderedVertex<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return data type for [`dijkstra`] and [`dijkstra unweighted`].
|
/// Return data type for [`dijkstra`] and [`dijkstra_unweighted`].
|
||||||
pub struct DijkstraResult<V: Copy> {
|
pub struct DijkstraResult<V: Copy> {
|
||||||
/// Vertex map of minimum distances from a given `source` vertex.
|
/// Vertex map of minimum distances from a given `source` vertex.
|
||||||
pub distances: VertexMap<V, Option<u32>>,
|
pub distances: VertexMap<V, Option<u32>>,
|
||||||
|
|
||||||
/// Vertex map of predecessors on some shortest path from a given `source` vertex.
|
/// Vertex map of predecessors on some shortest path from a given `source` vertex.
|
||||||
pub predecessors: VertexMap<V, Option<V>>,
|
pub predecessors: VertexMap<V, Option<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Generalize the return type of the weight function.
|
// TODO: Generalize the return type of the weight function.
|
||||||
/// Dijkstra's algorithm with custom edge weights, returns minimum distances and predecessors.
|
/// [Dijkstra's algorithm] with custom edge weights, returns minimum distances and predecessors.
|
||||||
|
///
|
||||||
|
/// Calculates the shortest paths from `source` to all vertices in `graph` with edge weights given
|
||||||
|
/// by `weight` function. Returns the distances from `source` to each vertex, and the predecessors
|
||||||
|
/// of each vertex on some shortest path from `source` to that vertex. Returns `None` for any vertex
|
||||||
|
/// not connected to `source`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@@ -85,6 +89,8 @@ pub struct DijkstraResult<V: Copy> {
|
|||||||
/// assert_eq!(result.distances[target], Some(5));
|
/// assert_eq!(result.distances[target], Some(5));
|
||||||
/// assert_eq!(result.predecessors[target], Some(source));
|
/// assert_eq!(result.predecessors[target], Some(source));
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Dijkstra's algorithm]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
pub fn dijkstra<G, W>(graph: &G, source: G::Vertex, weight: W) -> DijkstraResult<G::Vertex>
|
pub fn dijkstra<G, W>(graph: &G, source: G::Vertex, weight: W) -> DijkstraResult<G::Vertex>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -100,7 +106,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dijkstra's algorithm with custom edge weights, returns minimum distances.
|
/// [Dijkstra's algorithm] with custom edge weights, returns minimum distances.
|
||||||
|
///
|
||||||
|
/// Calculates the shortest paths from `source` to all vertices in `graph` with edge weights given
|
||||||
|
/// by `weight` function. Returns the distances from `source` to each vertex. Returns `None` for any
|
||||||
|
/// vertex not connected to `source`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@@ -110,7 +120,7 @@ where
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use grapherity::prelude::*;
|
/// # use grapherity::prelude::*;
|
||||||
/// # use grapherity::algorithms::{dijkstra, dijkstra_distances};
|
/// # use grapherity::algorithms::dijkstra_distances;
|
||||||
/// # use grapherity::models::Graph;
|
/// # use grapherity::models::Graph;
|
||||||
/// let mut graph = Graph::new();
|
/// let mut graph = Graph::new();
|
||||||
/// let source = graph.add_vertex();
|
/// let source = graph.add_vertex();
|
||||||
@@ -122,6 +132,8 @@ where
|
|||||||
/// let distances = dijkstra_distances(&graph, source, |e| weights[e]);
|
/// let distances = dijkstra_distances(&graph, source, |e| weights[e]);
|
||||||
/// assert_eq!(distances[target], Some(5));
|
/// assert_eq!(distances[target], Some(5));
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Dijkstra's algorithm]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
pub fn dijkstra_distances<G, W>(
|
pub fn dijkstra_distances<G, W>(
|
||||||
graph: &G,
|
graph: &G,
|
||||||
source: G::Vertex,
|
source: G::Vertex,
|
||||||
@@ -134,8 +146,13 @@ where
|
|||||||
dijkstra_impl(graph, source, weight, |_, _| {})
|
dijkstra_impl(graph, source, weight, |_, _| {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dijkstra's algorithm with constant weights of *1* for all edges, returns minimum distances and
|
/// [Dijkstra's algorithm] with unit edge weights, returns minimum distances and predecessors.
|
||||||
/// predecessors.
|
///
|
||||||
|
/// Calculates the shortest paths from `source` to all vertices in an unweighted `graph`. Returns
|
||||||
|
/// the distances from `source` to each vertex, and the predecessors of each vertex on some shortest
|
||||||
|
/// path from `source` to that vertex. Returns `None` for any vertex not connected to `source`.
|
||||||
|
///
|
||||||
|
/// Prefer [`bfs`] for unweighted graphs, it has better time and space complexity.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@@ -145,7 +162,7 @@ where
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use grapherity::prelude::*;
|
/// # use grapherity::prelude::*;
|
||||||
/// # use grapherity::algorithms::{dijkstra, dijkstra_unweighted};
|
/// # use grapherity::algorithms::dijkstra_unweighted;
|
||||||
/// # use grapherity::models::Graph;
|
/// # use grapherity::models::Graph;
|
||||||
/// let mut graph = Graph::new();
|
/// let mut graph = Graph::new();
|
||||||
/// let source = graph.add_vertex();
|
/// let source = graph.add_vertex();
|
||||||
@@ -156,6 +173,8 @@ where
|
|||||||
/// assert_eq!(result.distances[target], Some(1));
|
/// assert_eq!(result.distances[target], Some(1));
|
||||||
/// assert_eq!(result.predecessors[target], Some(source));
|
/// assert_eq!(result.predecessors[target], Some(source));
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Dijkstra's algorithm]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
pub fn dijkstra_unweighted<G>(graph: &G, source: G::Vertex) -> DijkstraResult<G::Vertex>
|
pub fn dijkstra_unweighted<G>(graph: &G, source: G::Vertex) -> DijkstraResult<G::Vertex>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -163,7 +182,13 @@ where
|
|||||||
dijkstra(graph, source, |_| 1)
|
dijkstra(graph, source, |_| 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dijkstra's algorithm with constant weights of *1* for all edges, returns minimum distances.
|
/// [Dijkstra's algorithm] with unit edge weights, returns minimum distances.
|
||||||
|
///
|
||||||
|
/// Calculates the shortest paths from `source` to all vertices in an unweighted `graph`. Returns
|
||||||
|
/// the distances from `source` to each vertex. Returns `None` for any vertex not connected to
|
||||||
|
/// `source`.
|
||||||
|
///
|
||||||
|
/// Prefer [`bfs_distances`] for unweighted graphs, it has better time and space complexity.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@@ -173,7 +198,7 @@ where
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use grapherity::prelude::*;
|
/// # use grapherity::prelude::*;
|
||||||
/// # use grapherity::algorithms::{dijkstra, dijkstra_distances_unweighted};
|
/// # use grapherity::algorithms::dijkstra_distances_unweighted;
|
||||||
/// # use grapherity::models::Graph;
|
/// # use grapherity::models::Graph;
|
||||||
/// let mut graph = Graph::new();
|
/// let mut graph = Graph::new();
|
||||||
/// let source = graph.add_vertex();
|
/// let source = graph.add_vertex();
|
||||||
@@ -183,6 +208,8 @@ where
|
|||||||
/// let distances = dijkstra_distances_unweighted(&graph, source);
|
/// let distances = dijkstra_distances_unweighted(&graph, source);
|
||||||
/// assert_eq!(distances[target], Some(1));
|
/// assert_eq!(distances[target], Some(1));
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Dijkstra's algorithm]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
pub fn dijkstra_distances_unweighted<G>(
|
pub fn dijkstra_distances_unweighted<G>(
|
||||||
graph: &G,
|
graph: &G,
|
||||||
source: G::Vertex,
|
source: G::Vertex,
|
||||||
@@ -233,11 +260,44 @@ where
|
|||||||
distances
|
distances
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return data type for [`bfs`].
|
||||||
pub struct BfsResult<V: Copy> {
|
pub struct BfsResult<V: Copy> {
|
||||||
|
/// Vertex map of minimum distances from a given `source` vertex.
|
||||||
pub distances: VertexMap<V, Option<u32>>,
|
pub distances: VertexMap<V, Option<u32>>,
|
||||||
|
/// Vertex map of predecessors on some shortest path from a given `source` vertex.
|
||||||
pub predecessors: VertexMap<V, Option<V>>,
|
pub predecessors: VertexMap<V, Option<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Breadth-first search] traversal from `source`, returns distances and predecessors.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source`, exploring all neighbors before descending
|
||||||
|
/// further. Returns the distances from `source` to each vertex, and the predecessors of each vertex
|
||||||
|
/// on some shortest path from `source` to that vertex. Returns `None` for any vertex not connected
|
||||||
|
/// to `source`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::bfs;
|
||||||
|
/// # 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 = bfs(&graph, source);
|
||||||
|
/// assert_eq!(result.distances[target], Some(1));
|
||||||
|
/// assert_eq!(result.predecessors[target], Some(source));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
pub fn bfs<G>(graph: &G, source: G::Vertex) -> BfsResult<G::Vertex>
|
pub fn bfs<G>(graph: &G, source: G::Vertex) -> BfsResult<G::Vertex>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -253,6 +313,34 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Breadth-first search] traversal from `source`, returns distances.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source`, exploring all neighbors before descending
|
||||||
|
/// further. Returns the distances from `source` to each vertex. Returns `None` for any vertex not
|
||||||
|
/// connected to `source`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::bfs_distances;
|
||||||
|
/// # 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 = bfs_distances(&graph, source);
|
||||||
|
/// assert_eq!(distances[target], Some(1));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
pub fn bfs_distances<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, Option<u32>>
|
pub fn bfs_distances<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, Option<u32>>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -260,6 +348,33 @@ where
|
|||||||
bfs_impl(graph, source, |_, _| true).distances
|
bfs_impl(graph, source, |_, _| true).distances
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Breadth-first search] from `source` for `target`, returns the distance.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source` until `target` is found, exploring all
|
||||||
|
/// neighbors before descending further. Returns the minimum distance from `source` to `target` if
|
||||||
|
/// `target` is a valid vertex of `graph` connected to `source`, or `None` otherwise.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::bfs_find;
|
||||||
|
/// # use grapherity::models::Graph;
|
||||||
|
/// let mut graph = Graph::new();
|
||||||
|
/// let source = graph.add_vertex();
|
||||||
|
/// let target = graph.add_vertex();
|
||||||
|
/// graph.add_edge(source, target);
|
||||||
|
///
|
||||||
|
/// assert_eq!(bfs_find(&graph, source, target), Some(1));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
pub fn bfs_find<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> Option<u32>
|
pub fn bfs_find<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> Option<u32>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -267,6 +382,35 @@ where
|
|||||||
bfs_find_where(graph, source, |v| v == target).map(|(_, distance)| distance)
|
bfs_find_where(graph, source, |v| v == target).map(|(_, distance)| distance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Breadth-first search] from `source` for a vertex matching `predicate`, returns the vertex and
|
||||||
|
/// its distance.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source` until a vertex satisfying `predicate` is
|
||||||
|
/// found, exploring all neighbors before descending further. Returns the first vertex satisfying
|
||||||
|
/// `predicate` and its minimum distance from `source`, or `None` if no such vertex is connected to
|
||||||
|
/// `source`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::bfs_find_where;
|
||||||
|
/// # use grapherity::models::Graph;
|
||||||
|
/// let mut graph = Graph::new();
|
||||||
|
/// let source = graph.add_vertex();
|
||||||
|
/// let target = graph.add_vertex();
|
||||||
|
/// graph.add_edge(source, target);
|
||||||
|
///
|
||||||
|
/// assert_eq!(bfs_find_where(&graph, source, |v| v == target), Some((target, 1)));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Breadth-first search]: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
pub fn bfs_find_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<(G::Vertex, u32)>
|
pub fn bfs_find_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<(G::Vertex, u32)>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -315,11 +459,44 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return data type for [`dfs`].
|
||||||
pub struct DfsResult<V: Copy> {
|
pub struct DfsResult<V: Copy> {
|
||||||
|
/// Vertex map indicating which vertices were visited during the search.
|
||||||
pub visited: VertexMap<V, bool>,
|
pub visited: VertexMap<V, bool>,
|
||||||
|
/// Vertex map of predecessors on the DFS tree path from a given `source` vertex.
|
||||||
pub predecessors: VertexMap<V, Option<V>>,
|
pub predecessors: VertexMap<V, Option<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Depth-first search] traversal from `source`, returns visited vertices and predecessors.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source`, exploring each branch as far as possible
|
||||||
|
/// before backtracking. Returns for each vertex whether it was visited, and the predecessors of
|
||||||
|
/// each vertex on the DFS tree path from `source` to that vertex. Any vertex not connected to
|
||||||
|
/// `source` is marked unvisited and has no predecessor.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::dfs;
|
||||||
|
/// # 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 = dfs(&graph, source);
|
||||||
|
/// assert!(result.visited[target]);
|
||||||
|
/// assert_eq!(result.predecessors[target], Some(source));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
pub fn dfs<G>(graph: &G, source: G::Vertex) -> DfsResult<G::Vertex>
|
pub fn dfs<G>(graph: &G, source: G::Vertex) -> DfsResult<G::Vertex>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -335,6 +512,34 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Depth-first search] traversal from `source`, returns visited vertices.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source`, exploring each branch as far as possible
|
||||||
|
/// before backtracking. Returns a map indicating which vertices were visited, i.e. which vertices
|
||||||
|
/// are connected to `source`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::dfs_visited;
|
||||||
|
/// # 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 visited = dfs_visited(&graph, source);
|
||||||
|
/// assert!(visited[target]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
pub fn dfs_visited<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, bool>
|
pub fn dfs_visited<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, bool>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -342,6 +547,33 @@ where
|
|||||||
dfs_impl(graph, source, |_, _| true).visited
|
dfs_impl(graph, source, |_, _| true).visited
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Depth-first search] from `source` for `target`, returns whether it was found.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source` until `target` is found, exploring each
|
||||||
|
/// branch as far as possible before backtracking. Returns `true` if `target` is a valid vertex of
|
||||||
|
/// `graph` connected to `source`, or `false` otherwise.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::dfs_find;
|
||||||
|
/// # use grapherity::models::Graph;
|
||||||
|
/// let mut graph = Graph::new();
|
||||||
|
/// let source = graph.add_vertex();
|
||||||
|
/// let target = graph.add_vertex();
|
||||||
|
/// graph.add_edge(source, target);
|
||||||
|
///
|
||||||
|
/// assert!(dfs_find(&graph, source, target));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
pub fn dfs_find<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> bool
|
pub fn dfs_find<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> bool
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -349,6 +581,33 @@ where
|
|||||||
dfs_find_where(graph, source, |v| v == target).is_some()
|
dfs_find_where(graph, source, |v| v == target).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Depth-first search] from `source` for a vertex matching `predicate`, returns the vertex.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source` until a vertex satisfying `predicate` is
|
||||||
|
/// found, exploring each branch as far as possible before backtracking. Returns the first vertex
|
||||||
|
/// satisfying `predicate`, or `None` if no such vertex is connected to `source`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::dfs_find_where;
|
||||||
|
/// # use grapherity::models::Graph;
|
||||||
|
/// let mut graph = Graph::new();
|
||||||
|
/// let source = graph.add_vertex();
|
||||||
|
/// let target = graph.add_vertex();
|
||||||
|
/// graph.add_edge(source, target);
|
||||||
|
///
|
||||||
|
/// assert_eq!(dfs_find_where(&graph, source, |v| v == target), Some(target));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
pub fn dfs_find_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<G::Vertex>
|
pub fn dfs_find_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<G::Vertex>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -396,6 +655,35 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Depth-first search] from `source` for `target`, returns the path as a sequence of edges.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source` until `target` is found, exploring each
|
||||||
|
/// branch as far as possible before backtracking. Returns some path from `source` to `target` as a
|
||||||
|
/// sequence of edges in traversal order if `target` is a valid vertex of `graph` connected to
|
||||||
|
/// `source`, or `None` otherwise. The returned path is empty if and only if `source` equals
|
||||||
|
/// `target`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::dfs_find_path;
|
||||||
|
/// # 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);
|
||||||
|
///
|
||||||
|
/// assert_eq!(dfs_find_path(&graph, source, target), Some(vec![e]));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
pub fn dfs_find_path<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> Option<Vec<G::Edge>>
|
pub fn dfs_find_path<G>(graph: &G, source: G::Vertex, target: G::Vertex) -> Option<Vec<G::Edge>>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
@@ -403,6 +691,36 @@ where
|
|||||||
dfs_find_path_where(graph, source, |v| v == target)
|
dfs_find_path_where(graph, source, |v| v == target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Depth-first search] from `source` for a vertex matching `predicate`, returns the path as a
|
||||||
|
/// sequence of edges.
|
||||||
|
///
|
||||||
|
/// Traverses vertices in `graph` starting from `source` until a vertex satisfying `predicate` is
|
||||||
|
/// found, exploring each branch as far as possible before backtracking. Returns some path from
|
||||||
|
/// `source` to the first vertex satisfying `predicate` as a sequence of edges in traversal order,
|
||||||
|
/// or `None` if no such vertex is connected to `source`. The returned path is empty if and only if
|
||||||
|
/// `source` satisfies `predicate`.
|
||||||
|
///
|
||||||
|
/// Time complexity is *O(|V| + |E|)*, space complexity is *O(|V|)*.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `source` is not a valid vertex of `graph`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use grapherity::prelude::*;
|
||||||
|
/// # use grapherity::algorithms::dfs_find_path_where;
|
||||||
|
/// # 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);
|
||||||
|
///
|
||||||
|
/// assert_eq!(dfs_find_path_where(&graph, source, |v| v == target), Some(vec![e]));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Depth-first search]: https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
pub fn dfs_find_path_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<Vec<G::Edge>>
|
pub fn dfs_find_path_where<G, P>(graph: &G, source: G::Vertex, predicate: P) -> Option<Vec<G::Edge>>
|
||||||
where
|
where
|
||||||
G: GraphTopology,
|
G: GraphTopology,
|
||||||
|
|||||||
Reference in New Issue
Block a user