├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── bft.rs ├── dft_cycles.rs ├── dft_longest_paths.rs ├── dft_paths.rs ├── dft_post.rs ├── dft_post_rev.rs ├── dft_pre.rs ├── dft_pre_rev.rs └── lib.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - "**.md" 8 | pull_request: 9 | branches: [ master ] 10 | paths-ignore: 11 | - "**.md" 12 | 13 | env: 14 | CARGO_TERM_COLOR: always 15 | 16 | jobs: 17 | build: 18 | 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Build 24 | run: cargo build --verbose 25 | - name: Run tests 26 | run: cargo test --verbose 27 | - name: Fail on warning 28 | env: 29 | RUSTFLAGS: -D warnings 30 | run: cargo build --verbose 31 | - name: Rustfmt 32 | run: cargo fmt -- --check 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | - nightly 6 | jobs: 7 | allow_failures: 8 | - rust: nightly 9 | fast_finish: true 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 0.1.2 (2020-03-13) 4 | 5 | - Added All Cycles (Paths) ([`DftCycles`]) 6 | 7 | [`DftCycles`]: https://docs.rs/traversal/*/traversal/struct.DftCycles.html 8 | 9 | ## ~~Version 0.1.1 (2020-03-13)~~ - Yanked 10 | 11 | This release was yanked as the crate name wrong. 12 | 13 | *Changes have been moved to the next version.* 14 | 15 | ## Version 0.1.0 (2020-03-11) 16 | 17 | - Added [Breadth-First Traversal] ([`Bft`]) 18 | - Added [Depth-First Traversal] in Pre-Order ([`DftPre`]) 19 | - Added [Depth-First Traversal] in Post-Order ([`DftPost`]) 20 | - Added Reverse [Depth-First Traversal] in Pre-Order ([`DftPreRev`]) 21 | - Added Reverse [Depth-First Traversal] in Post-Order ([`DftPostRev`]) 22 | 23 | - Added All Paths ([`DftPaths`]) 24 | - Added Longest Paths ([`DftLongestPaths`]) 25 | 26 | [Breadth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 27 | [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 28 | 29 | [`Bft`]: https://docs.rs/traversal/*/traversal/struct.Bft.html 30 | [`DftPre`]: https://docs.rs/traversal/*/traversal/struct.DftPre.html 31 | [`DftPost`]: https://docs.rs/traversal/*/traversal/struct.DftPost.html 32 | [`DftPreRev`]: https://docs.rs/traversal/*/traversal/struct.DftPreRev.html 33 | [`DftPostRev`]: https://docs.rs/traversal/*/traversal/struct.DftPostRev.html 34 | 35 | [`DftPaths`]: https://docs.rs/traversal/*/traversal/struct.DftPaths.html 36 | [`DftLongestPaths`]: https://docs.rs/traversal/*/traversal/struct.DftLongestPaths.html 37 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "traversal" 3 | version = "0.1.2" 4 | authors = ["Christian Vallentin"] 5 | edition = "2018" 6 | description = "Generic and lazy tree traversal algorithms" 7 | keywords = ["tree", "graph", "traversal", "traverse", "search"] 8 | categories = ["algorithms", "data-structures"] 9 | license = "MIT" 10 | repository = "https://github.com/vallentin/traversal" 11 | documentation = "https://docs.rs/traversal" 12 | readme = "README.md" 13 | exclude = [".travis.yml"] 14 | 15 | [badges] 16 | travis-ci = { repository = "vallentin/traversal" } 17 | 18 | [dependencies] 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Christian Vallentin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # traversal 2 | 3 | [![Build Status](https://github.com/vallentin/traversal/workflows/Rust/badge.svg)](https://github.com/vallentin/traversal/actions?query=workflow%3ARust) 4 | [![Build Status](https://travis-ci.org/vallentin/traversal.svg?branch=master)](https://travis-ci.org/vallentin/traversal) 5 | [![Latest Version](https://img.shields.io/crates/v/traversal.svg)](https://crates.io/crates/traversal) 6 | [![Docs](https://docs.rs/traversal/badge.svg)](https://docs.rs/traversal) 7 | [![License](https://img.shields.io/github/license/vallentin/traversal.svg)](https://github.com/vallentin/traversal) 8 | 9 | Traversal implements generic and lazy tree traversal algorithms. 10 | 11 | Includes: 12 | - [Breadth-First Traversal] ([`Bft`]) 13 | - [Depth-First Traversal] in Pre-Order ([`DftPre`]) 14 | - [Depth-First Traversal] in Post-Order ([`DftPost`]) 15 | - Reverse [Depth-First Traversal] in Pre-Order ([`DftPreRev`]) 16 | - Reverse [Depth-First Traversal] in Post-Order ([`DftPostRev`]) 17 | 18 | - All Paths ([`DftPaths`]) 19 | - Longest Paths ([`DftLongestPaths`]) 20 | - All Cycles (Paths) ([`DftCycles`]) 21 | 22 | [Breadth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 23 | [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 24 | 25 | ### Generic 26 | 27 | Traversal uses [generics] (or [type parameters]) to be 28 | flexible to use, and easy to implement and fit into existing 29 | architecture. 30 | 31 | [generics]: https://doc.rust-lang.org/rust-by-example/generics.html 32 | [type parameters]: https://doc.rust-lang.org/reference/types/parameters.html 33 | 34 | ### Laziness 35 | 36 | Laziness or [lazy evaluation] refers to evaluation being delayed 37 | until needed. 38 | 39 | Traversal delays processing `Node`s and fetching child `Node`s 40 | until [`Iterator::next`][`next`] is called. 41 | When [`next`] is called, then traversal only processes the 42 | `Node`s required for this iteration. 43 | 44 | [lazy evaluation]: https://en.wikipedia.org/wiki/Lazy_evaluation 45 | 46 | *From Rust's docs:* 47 | 48 | > *Iterators (and iterator [adapters]) are lazy. This means that just 49 | > creating an iterator doesn't do a whole lot. Nothing really happens 50 | > until you call [`next`].* 51 | > 52 | > — [`Iterator`] - [Laziness] 53 | 54 | [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 55 | [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next 56 | 57 | [Laziness]: https://doc.rust-lang.org/std/iter/index.html#laziness 58 | [adapters]: https://doc.rust-lang.org/std/iter/index.html#adapters 59 | 60 | ## Usage 61 | 62 | Add this to your `Cargo.toml`: 63 | 64 | ```toml 65 | [dependencies] 66 | traversal = "0.1" 67 | ``` 68 | 69 | ## Releases 70 | 71 | Release notes are available in the repo at [CHANGELOG.md]. 72 | 73 | [CHANGELOG.md]: CHANGELOG.md 74 | 75 | ## Algorithms 76 | 77 | ```text 78 | A 79 | / \ 80 | B C 81 | / \ / \ 82 | D E F G 83 | ``` 84 | 85 | Given the above tree, then the following are the orders, 86 | that each individual iterator / traversal algorithm produces. 87 | 88 | | Algorithm | Order | 89 | |-----------|-------| 90 | | [`Bft`] (Breadth-First Traversal) | A, B, C, D, E, F, G | 91 | | [`DftPre`] (Depth-First Traversal in Pre-Order) | A, B, D, E, C, F, G | 92 | | [`DftPost`] (Depth-First Traversal in Post-Order) | D, E, B, F, G, C, A | 93 | | [`DftPreRev`] (Reverse Depth-First Traversal in Pre-Order) | G, F, C, E, D, B, A | 94 | | [`DftPostRev`] (Reverse Depth-First Traversal in Post-Order) | A, C, G, F, B, E, D | 95 | 96 | *See each individual algorithm for code examples.* 97 | 98 | [`Bft`]: https://docs.rs/traversal/*/traversal/struct.Bft.html 99 | [`DftPre`]: https://docs.rs/traversal/*/traversal/struct.DftPre.html 100 | [`DftPost`]: https://docs.rs/traversal/*/traversal/struct.DftPost.html 101 | [`DftPreRev`]: https://docs.rs/traversal/*/traversal/struct.DftPreRev.html 102 | [`DftPostRev`]: https://docs.rs/traversal/*/traversal/struct.DftPostRev.html 103 | 104 | ### All Paths and Longest Paths 105 | 106 | [`DftPaths`] and [`DftLongestPaths`] are utilities for 107 | iterating all paths and the longest paths in a tree. 108 | 109 | *Given the same tree as the previous examples, then 110 | [`DftPaths`] and [`DftLongestPaths`] produce the 111 | following paths.* 112 | 113 | [`DftPaths`]: 114 | - A, B 115 | - A, B, D 116 | - A, B, E 117 | - A, C 118 | - A, C, F 119 | - A, C, G 120 | 121 | [`DftLongestPaths`]: 122 | - A, B, D 123 | - A, B, E 124 | - A, C, F 125 | - A, C, G 126 | 127 | *See each individual algorithm for code examples.* 128 | 129 | [`DftPaths`]: https://docs.rs/traversal/*/traversal/struct.DftPaths.html 130 | [`DftLongestPaths`]: https://docs.rs/traversal/*/traversal/struct.DftLongestPaths.html 131 | 132 | ## Cycles 133 | 134 | ```text 135 | A <---+ 136 | / \ | 137 | B D >-+ 138 | | | | 139 | C E >-+ 140 | ``` 141 | 142 | [`DftCycles`]: 143 | - A -> D (*implies D is connected with A*) 144 | - A -> D -> E 145 | 146 | *See each individual algorithm for code examples.* 147 | 148 | [`DftCycles`]: https://docs.rs/traversal/*/traversal/struct.DftCycles.html 149 | -------------------------------------------------------------------------------- /src/bft.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::iter::{Extend, FusedIterator}; 3 | 4 | /// [Breadth-First Traversal] (or Level Order Traversal). 5 | /// 6 | /// [Breadth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 7 | /// 8 | /// # Cycles 9 | /// 10 | /// `Bft` does not handle cycles. If any 11 | /// cycles are present, then `Bft` will 12 | /// result in an infinite (never ending) 13 | /// [`Iterator`]. 14 | /// 15 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 16 | /// 17 | /// # Example 18 | /// 19 | /// ``` 20 | /// use traversal::Bft; 21 | /// 22 | /// struct Node(&'static str, &'static [Node]); 23 | /// 24 | /// let tree = Node("A", &[ 25 | /// Node("B", &[ 26 | /// Node("D", &[]), 27 | /// Node("E", &[]) 28 | /// ]), 29 | /// Node("C", &[ 30 | /// Node("F", &[]), 31 | /// Node("G", &[]) 32 | /// ]), 33 | /// ]); 34 | /// 35 | /// // `&tree` represents the root `Node`. 36 | /// // The `FnMut(&Node) -> Iterator` returns 37 | /// // an `Iterator` to get the child `Node`s. 38 | /// let iter = Bft::new(&tree, |node| node.1.iter()); 39 | /// 40 | /// // Map `Iterator` into `Iterator` 41 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 42 | /// 43 | /// assert_eq!(iter.next(), Some((0, "A"))); 44 | /// assert_eq!(iter.next(), Some((1, "B"))); 45 | /// assert_eq!(iter.next(), Some((1, "C"))); 46 | /// assert_eq!(iter.next(), Some((2, "D"))); 47 | /// assert_eq!(iter.next(), Some((2, "E"))); 48 | /// assert_eq!(iter.next(), Some((2, "F"))); 49 | /// assert_eq!(iter.next(), Some((2, "G"))); 50 | /// assert_eq!(iter.next(), None); 51 | /// ``` 52 | #[allow(missing_debug_implementations)] 53 | #[derive(Clone)] 54 | pub struct Bft<'a, T, F, I> 55 | where 56 | T: ?Sized, 57 | F: FnMut(&'a T) -> I, 58 | I: Iterator, 59 | { 60 | queue: VecDeque<(usize, &'a T)>, 61 | iter_children: F, 62 | } 63 | 64 | impl<'a, T, F, I> Bft<'a, T, F, I> 65 | where 66 | T: ?Sized, 67 | F: FnMut(&'a T) -> I, 68 | I: Iterator, 69 | { 70 | /// Creates a `Bft`, where `root` is the 71 | /// starting `Node`. 72 | /// 73 | /// The `iter_children` [`FnMut`] is (lazily) called 74 | /// for each `Node` as needed, where the 75 | /// returned [`Iterator`] produces the child 76 | /// `Node`s for the given `Node`. 77 | /// 78 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 79 | /// 80 | /// *[See `Bft` for more information.][`Bft`]* 81 | /// 82 | /// [`Bft`]: struct.Bft.html 83 | /// 84 | /// # "`FnOnce`" 85 | /// 86 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 87 | /// a `Node`, as `iter_children` is at most called once for 88 | /// each individual `Node`. 89 | /// 90 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 91 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 92 | /// 93 | /// # `FusedIterator` 94 | /// 95 | /// While `Bft` does not require [`FusedIterator`], 96 | /// it assumes that no `Node`s are produced after 97 | /// a `None`. 98 | /// 99 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 100 | #[inline] 101 | pub fn new(root: &'a T, iter_children: F) -> Self { 102 | Self { 103 | queue: VecDeque::from(vec![(0, root)]), 104 | iter_children, 105 | } 106 | } 107 | } 108 | 109 | impl<'a, T, F, I> Iterator for Bft<'a, T, F, I> 110 | where 111 | T: ?Sized, 112 | F: FnMut(&'a T) -> I, 113 | I: Iterator, 114 | { 115 | type Item = (usize, &'a T); 116 | 117 | #[inline] 118 | fn next(&mut self) -> Option { 119 | if let Some((depth, node)) = self.queue.pop_front() { 120 | let children = (self.iter_children)(node); 121 | self.queue.extend(children.map(|child| (depth + 1, child))); 122 | 123 | Some((depth, node)) 124 | } else { 125 | None 126 | } 127 | } 128 | } 129 | 130 | impl<'a, T, F, I> FusedIterator for Bft<'a, T, F, I> 131 | where 132 | T: ?Sized, 133 | F: FnMut(&'a T) -> I, 134 | I: Iterator, 135 | { 136 | } 137 | 138 | #[cfg(test)] 139 | mod tests { 140 | use super::*; 141 | 142 | struct Node(&'static str, &'static [Node]); 143 | 144 | #[test] 145 | fn bft() { 146 | #[rustfmt::skip] 147 | let tree = Node("A", &[ 148 | Node("B", &[ 149 | Node("D", &[]), 150 | Node("E", &[ 151 | Node("H", &[]) 152 | ])]), 153 | Node("C", &[ 154 | Node("F", &[ 155 | Node("I", &[]) 156 | ]), 157 | Node("G", &[])]), 158 | ]); 159 | 160 | let iter = Bft::new(&tree, |node| node.1.iter()); 161 | let mut iter = iter.map(|(depth, node)| (depth, node.0)); 162 | 163 | assert_eq!(iter.next(), Some((0, "A"))); 164 | assert_eq!(iter.next(), Some((1, "B"))); 165 | assert_eq!(iter.next(), Some((1, "C"))); 166 | assert_eq!(iter.next(), Some((2, "D"))); 167 | assert_eq!(iter.next(), Some((2, "E"))); 168 | assert_eq!(iter.next(), Some((2, "F"))); 169 | assert_eq!(iter.next(), Some((2, "G"))); 170 | assert_eq!(iter.next(), Some((3, "H"))); 171 | assert_eq!(iter.next(), Some((3, "I"))); 172 | assert_eq!(iter.next(), None); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/dft_cycles.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::hash::Hash; 3 | use std::iter::FusedIterator; 4 | 5 | /// Produces all [cycle] paths using 6 | /// [Depth-First Traversal] (in Pre-Order). 7 | /// 8 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 9 | /// 10 | /// `DftCycles` produces all paths that contain a [cycle]. 11 | /// Thereby all [`Vec`]``s produced are a path 12 | /// containing a cycle, as in [`last()`] is connected 13 | /// to [`first()`]. 14 | /// 15 | /// [`Vec`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html 16 | /// [`last()`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.last 17 | /// [`first()`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.first 18 | /// 19 | /// [cycle]: https://en.wikipedia.org/wiki/Cycle_(graph_theory) 20 | /// 21 | /// # Example 22 | /// 23 | /// ``` 24 | /// use traversal::DftCycles; 25 | /// 26 | /// #[derive(PartialEq, Eq, Hash)] 27 | /// struct Vertex(&'static str, Vec); 28 | /// 29 | /// // A <-+ 30 | /// // /|\ | 31 | /// // B | C | 32 | /// // \|/ | 33 | /// // D >-+ 34 | /// // 35 | /// // Cycles: 36 | /// // - A -> B -> D -> A 37 | /// // - A -> D -> A 38 | /// // - A -> C -> D -> A 39 | /// let graph = vec![ 40 | /// Vertex("A", vec![1, 3, 2]), // 0 41 | /// Vertex("B", vec![3]), // 1 42 | /// Vertex("C", vec![3]), // 2 43 | /// Vertex("D", vec![0]), // 3 44 | /// ]; 45 | /// 46 | /// let start = &graph[0]; // A 47 | /// 48 | /// // `&tree` represents the root `Vertex`. 49 | /// // The `FnMut(&Vertex) -> Iterator` returns 50 | /// // an `Iterator` to get the connected vertices. 51 | /// let mut cycles = DftCycles::new(start, |vertex| { 52 | /// vertex.1.iter().map(|&i| { 53 | /// &graph[i] 54 | /// }) 55 | /// }); 56 | /// 57 | /// // Map `Iterator>` into `Iterator>` 58 | /// let mut cycles = cycles.map(|path| path.iter().map(|vertex| vertex.0).collect::>()); 59 | /// 60 | /// assert_eq!(cycles.next(), Some(vec!["A", "B", "D"])); 61 | /// assert_eq!(cycles.next(), Some(vec!["A", "D"])); 62 | /// assert_eq!(cycles.next(), Some(vec!["A", "C", "D"])); 63 | /// assert_eq!(cycles.next(), None); 64 | /// ``` 65 | #[allow(missing_debug_implementations)] 66 | #[derive(Clone)] 67 | pub struct DftCycles<'a, T, F, I> 68 | where 69 | T: ?Sized, 70 | F: FnMut(&'a T) -> I, 71 | I: Iterator, 72 | T: Eq + Hash, 73 | { 74 | queue: Vec<(usize, &'a T)>, 75 | path: Vec<&'a T>, 76 | visited: HashSet<&'a T>, 77 | iter_connections: F, 78 | } 79 | 80 | impl<'a, T, F, I> DftCycles<'a, T, F, I> 81 | where 82 | T: ?Sized, 83 | F: FnMut(&'a T) -> I, 84 | I: Iterator, 85 | T: Eq + Hash, 86 | { 87 | /// Creates a `DftCycles`, where `root` is the 88 | /// starting `Node`. 89 | /// 90 | /// The `iter_connections` [`FnMut`] is (lazily) called 91 | /// for each `Node` as needed, where the 92 | /// returned [`Iterator`] produces the child 93 | /// `Node`s for the given `Node`. 94 | /// 95 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 96 | /// 97 | /// *[See `DftCycles` for more information.][`DftCycles`]* 98 | /// 99 | /// [`DftCycles`]: struct.DftCycles.html 100 | /// 101 | /// # "`FnOnce`" 102 | /// 103 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 104 | /// a `Node`, as `iter_connections` is at most called once for 105 | /// each individual `Node`. 106 | /// 107 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 108 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 109 | /// 110 | /// # `FusedIterator` 111 | /// 112 | /// While `DftCycles` does not require [`FusedIterator`], 113 | /// it assumes that no `Node`s are produced after 114 | /// a `None`. 115 | /// 116 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 117 | #[inline] 118 | pub fn new(root: &'a T, iter_connections: F) -> Self { 119 | Self { 120 | queue: vec![(0, root)], 121 | path: Vec::new(), 122 | visited: HashSet::new(), 123 | iter_connections, 124 | } 125 | } 126 | } 127 | 128 | impl<'a, T, F, I> Iterator for DftCycles<'a, T, F, I> 129 | where 130 | T: ?Sized, 131 | F: FnMut(&'a T) -> I, 132 | I: Iterator, 133 | T: Eq + Hash, 134 | { 135 | type Item = Vec<&'a T>; 136 | 137 | #[inline] 138 | fn next(&mut self) -> Option { 139 | while let Some((depth, node)) = self.queue.pop() { 140 | if depth < self.path.len() { 141 | let (path, visited) = (&mut self.path, &mut self.visited); 142 | 143 | path.drain(depth..).for_each(|node| { 144 | visited.remove(node); 145 | }); 146 | } 147 | 148 | if !self.visited.insert(node) { 149 | return Some(self.path.clone()); 150 | } 151 | 152 | self.path.push(node); 153 | 154 | let children = (self.iter_connections)(node); 155 | 156 | let children = children.collect::>(); 157 | let children = children.into_iter().rev(); 158 | 159 | self.queue.extend(children.map(|child| (depth + 1, child))); 160 | } 161 | 162 | None 163 | } 164 | } 165 | 166 | impl<'a, T, F, I> FusedIterator for DftCycles<'a, T, F, I> 167 | where 168 | T: ?Sized, 169 | F: FnMut(&'a T) -> I, 170 | I: Iterator, 171 | T: Eq + Hash, 172 | { 173 | } 174 | 175 | #[cfg(test)] 176 | mod tests { 177 | use super::*; 178 | 179 | #[derive(PartialEq, Eq, Hash)] 180 | struct Vertex(&'static str, Vec); 181 | 182 | #[test] 183 | fn dft_cycles() { 184 | // A <----+ 185 | // / \ | 186 | // B >- D >-+ 187 | // \ / | 188 | // C >----+ 189 | // 190 | // Cycles: 191 | // - A -> B -> C -> A 192 | // - A -> B -> C -> D -> A 193 | // - A -> B -> D -> A 194 | // - A -> D -> A 195 | let graph = vec![ 196 | Vertex("A", vec![1, 3]), // 0 197 | Vertex("B", vec![2, 3]), // 1 198 | Vertex("C", vec![0, 3]), // 2 199 | Vertex("D", vec![0]), // 3 200 | ]; 201 | 202 | let start = &graph[0]; // A 203 | 204 | let cycles = DftCycles::new(start, |vertex| vertex.1.iter().map(|&i| &graph[i])); 205 | let mut cycles = cycles.map(|path| path.iter().map(|vertex| vertex.0).collect::>()); 206 | 207 | assert_eq!(cycles.next(), Some(vec!["A", "B", "C"])); 208 | assert_eq!(cycles.next(), Some(vec!["A", "B", "C", "D"])); 209 | assert_eq!(cycles.next(), Some(vec!["A", "B", "D"])); 210 | assert_eq!(cycles.next(), Some(vec!["A", "D"])); 211 | assert_eq!(cycles.next(), None); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/dft_longest_paths.rs: -------------------------------------------------------------------------------- 1 | use std::iter::FusedIterator; 2 | use std::mem; 3 | 4 | use crate::DftPre; 5 | 6 | /// Produces the longest paths using 7 | /// [Depth-First Traversal] (in Pre-Order). 8 | /// 9 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 10 | /// 11 | /// # Cycles 12 | /// 13 | /// `DftLongestPaths` does not handle cycles. If any 14 | /// cycles are present, then `DftLongestPaths` will 15 | /// result in an infinite (never ending) 16 | /// [`Iterator`]. 17 | /// 18 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 19 | /// 20 | /// # Example 21 | /// 22 | /// ``` 23 | /// use traversal::DftLongestPaths; 24 | /// 25 | /// struct Node(&'static str, &'static [Node]); 26 | /// 27 | /// let tree = Node("A", &[ 28 | /// Node("B", &[ 29 | /// Node("C", &[]), 30 | /// Node("D", &[]) 31 | /// ]), 32 | /// Node("E", &[ 33 | /// Node("F", &[]), 34 | /// Node("G", &[]) 35 | /// ]), 36 | /// ]); 37 | /// 38 | /// // `&tree` represents the root `Node`. 39 | /// // The `FnMut(&Node) -> Iterator` returns 40 | /// // an `Iterator` to get the child `Node`s. 41 | /// let iter = DftLongestPaths::new(&tree, |node| node.1.iter()); 42 | /// 43 | /// // Map `Iterator>` into `Iterator>` 44 | /// let mut iter = iter.map(|path| path.iter().map(|node| node.0).collect::>()); 45 | /// 46 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "C"])); 47 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "D"])); 48 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "F"])); 49 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "G"])); 50 | /// assert_eq!(iter.next(), None); 51 | /// ``` 52 | #[allow(missing_debug_implementations)] 53 | #[derive(Clone)] 54 | pub struct DftLongestPaths<'a, T, F, I> 55 | where 56 | T: ?Sized, 57 | F: FnMut(&'a T) -> I, 58 | I: Iterator, 59 | { 60 | path: Vec<&'a T>, 61 | iter: DftPre<'a, T, F, I>, 62 | } 63 | 64 | impl<'a, T, F, I> DftLongestPaths<'a, T, F, I> 65 | where 66 | T: ?Sized, 67 | F: FnMut(&'a T) -> I, 68 | I: Iterator, 69 | { 70 | /// Creates a `DftLongestPaths`, where `root` is the 71 | /// starting `Node`. 72 | /// 73 | /// The `iter_children` [`FnMut`] is (lazily) called 74 | /// for each `Node` as needed, where the 75 | /// returned [`Iterator`] produces the child 76 | /// `Node`s for the given `Node`. 77 | /// 78 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 79 | /// 80 | /// 81 | /// *[See `DftLongestPaths` for more information.][`DftLongestPaths`]* 82 | /// 83 | /// [`DftLongestPaths`]: struct.DftLongestPaths.html 84 | /// 85 | /// # "`FnOnce`" 86 | /// 87 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 88 | /// a `Node`, as `iter_children` is at most called once for 89 | /// each individual `Node`. 90 | /// 91 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 92 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 93 | /// 94 | /// # `FusedIterator` 95 | /// 96 | /// While `DftLongestPaths` does not require [`FusedIterator`], 97 | /// it assumes that no `Node`s are produced after 98 | /// a `None`. 99 | /// 100 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 101 | #[inline] 102 | pub fn new(root: &'a T, iter_children: F) -> Self { 103 | let mut iter = DftPre::new(root, iter_children); 104 | 105 | // Safe to use `unwrap` as `DftPre` with `root` at least produces `root` 106 | Self { 107 | path: vec![iter.next().unwrap().1], 108 | iter, 109 | } 110 | } 111 | } 112 | 113 | impl<'a, T, F, I> Iterator for DftLongestPaths<'a, T, F, I> 114 | where 115 | T: ?Sized, 116 | F: FnMut(&'a T) -> I, 117 | I: Iterator, 118 | { 119 | type Item = Vec<&'a T>; 120 | 121 | #[inline] 122 | fn next(&mut self) -> Option { 123 | if self.path.is_empty() { 124 | None 125 | } else { 126 | while let Some((depth, node)) = self.iter.next() { 127 | if self.path.len() > depth { 128 | let path = self.path.clone(); 129 | 130 | self.path.truncate(depth); 131 | self.path.push(node); 132 | 133 | return Some(path); 134 | } else { 135 | self.path.push(node); 136 | } 137 | } 138 | 139 | Some(mem::replace(&mut self.path, Vec::new())) 140 | } 141 | } 142 | } 143 | 144 | impl<'a, T, F, I> FusedIterator for DftLongestPaths<'a, T, F, I> 145 | where 146 | T: ?Sized, 147 | F: FnMut(&'a T) -> I, 148 | I: Iterator, 149 | { 150 | } 151 | 152 | #[cfg(test)] 153 | mod tests { 154 | use super::*; 155 | 156 | struct Node(&'static str, &'static [Node]); 157 | 158 | #[test] 159 | fn dft_longest_paths() { 160 | #[rustfmt::skip] 161 | let tree = Node("A", &[ 162 | Node("B", &[ 163 | Node("C", &[]), 164 | Node("D", &[ 165 | Node("E", &[]) 166 | ])]), 167 | Node("F", &[ 168 | Node("G", &[ 169 | Node("H", &[]) 170 | ]), 171 | Node("I", &[])]), 172 | ]); 173 | 174 | let iter = DftLongestPaths::new(&tree, |node| node.1.iter()); 175 | let mut iter = iter.map(|path| path.iter().map(|node| node.0).collect::>()); 176 | 177 | assert_eq!(iter.next(), Some(vec!["A", "B", "C"])); 178 | assert_eq!(iter.next(), Some(vec!["A", "B", "D", "E"])); 179 | assert_eq!(iter.next(), Some(vec!["A", "F", "G", "H"])); 180 | assert_eq!(iter.next(), Some(vec!["A", "F", "I"])); 181 | assert_eq!(iter.next(), None); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/dft_paths.rs: -------------------------------------------------------------------------------- 1 | use std::iter::FusedIterator; 2 | 3 | use crate::DftPre; 4 | 5 | /// Produces all paths using 6 | /// [Depth-First Traversal] (in Pre-Order). 7 | /// 8 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 9 | /// 10 | /// # Cycles 11 | /// 12 | /// `DftPaths` does not handle cycles. If any 13 | /// cycles are present, then `DftPaths` will 14 | /// result in an infinite (never ending) 15 | /// [`Iterator`]. 16 | /// 17 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 18 | /// 19 | /// # Example 20 | /// 21 | /// ``` 22 | /// use traversal::DftPaths; 23 | /// 24 | /// struct Node(&'static str, &'static [Node]); 25 | /// 26 | /// let tree = Node("A", &[ 27 | /// Node("B", &[ 28 | /// Node("C", &[]), 29 | /// Node("D", &[]) 30 | /// ]), 31 | /// Node("E", &[ 32 | /// Node("F", &[]), 33 | /// Node("G", &[]) 34 | /// ]), 35 | /// ]); 36 | /// 37 | /// // `&tree` represents the root `Node`. 38 | /// // The `FnMut(&Node) -> Iterator` returns 39 | /// // an `Iterator` to get the child `Node`s. 40 | /// let iter = DftPaths::new(&tree, |node| node.1.iter()); 41 | /// 42 | /// // Map `Iterator>` into `Iterator>` 43 | /// let mut iter = iter.map(|path| path.iter().map(|node| node.0).collect::>()); 44 | /// 45 | /// assert_eq!(iter.next(), Some(vec!["A", "B"])); 46 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "C"])); 47 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "D"])); 48 | /// assert_eq!(iter.next(), Some(vec!["A", "E"])); 49 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "F"])); 50 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "G"])); 51 | /// assert_eq!(iter.next(), None); 52 | /// ``` 53 | #[allow(missing_debug_implementations)] 54 | #[derive(Clone)] 55 | pub struct DftPaths<'a, T, F, I> 56 | where 57 | T: ?Sized, 58 | F: FnMut(&'a T) -> I, 59 | I: Iterator, 60 | { 61 | path: Vec<&'a T>, 62 | iter: DftPre<'a, T, F, I>, 63 | } 64 | 65 | impl<'a, T, F, I> DftPaths<'a, T, F, I> 66 | where 67 | T: ?Sized, 68 | F: FnMut(&'a T) -> I, 69 | I: Iterator, 70 | { 71 | /// Creates a `DftPaths`, where `root` is the 72 | /// starting `Node`. 73 | /// 74 | /// The `iter_children` [`FnMut`] is (lazily) called 75 | /// for each `Node` as needed, where the 76 | /// returned [`Iterator`] produces the child 77 | /// `Node`s for the given `Node`. 78 | /// 79 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 80 | /// 81 | /// *[See `DftPaths` for more information.][`DftPaths`]* 82 | /// 83 | /// [`DftPaths`]: struct.DftPaths.html 84 | /// 85 | /// # "`FnOnce`" 86 | /// 87 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 88 | /// a `Node`, as `iter_children` is at most called once for 89 | /// each individual `Node`. 90 | /// 91 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 92 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 93 | /// 94 | /// # `FusedIterator` 95 | /// 96 | /// While `DftPaths` does not require [`FusedIterator`], 97 | /// it assumes that no `Node`s are produced after 98 | /// a `None`. 99 | /// 100 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 101 | #[inline] 102 | pub fn new(root: &'a T, iter_children: F) -> Self { 103 | let mut iter = DftPre::new(root, iter_children); 104 | 105 | // Safe to use `unwrap` as `DftPre` with `root` at least produces `root` 106 | Self { 107 | path: vec![iter.next().unwrap().1], 108 | iter, 109 | } 110 | } 111 | } 112 | 113 | impl<'a, T, F, I> Iterator for DftPaths<'a, T, F, I> 114 | where 115 | T: ?Sized, 116 | F: FnMut(&'a T) -> I, 117 | I: Iterator, 118 | { 119 | type Item = Vec<&'a T>; 120 | 121 | #[inline] 122 | fn next(&mut self) -> Option { 123 | if let Some((depth, node)) = self.iter.next() { 124 | self.path.truncate(depth); 125 | self.path.push(node); 126 | 127 | Some(self.path.clone()) 128 | } else { 129 | None 130 | } 131 | } 132 | } 133 | 134 | impl<'a, T, F, I> FusedIterator for DftPaths<'a, T, F, I> 135 | where 136 | T: ?Sized, 137 | F: FnMut(&'a T) -> I, 138 | I: Iterator, 139 | { 140 | } 141 | 142 | #[cfg(test)] 143 | mod tests { 144 | use super::*; 145 | 146 | struct Node(&'static str, &'static [Node]); 147 | 148 | #[test] 149 | fn dft_paths() { 150 | #[rustfmt::skip] 151 | let tree = Node("A", &[ 152 | Node("B", &[ 153 | Node("C", &[]), 154 | Node("D", &[ 155 | Node("E", &[]) 156 | ])]), 157 | Node("F", &[ 158 | Node("G", &[ 159 | Node("H", &[]) 160 | ]), 161 | Node("I", &[])]), 162 | ]); 163 | 164 | let iter = DftPaths::new(&tree, |node| node.1.iter()); 165 | let mut iter = iter.map(|path| path.iter().map(|node| node.0).collect::>()); 166 | 167 | assert_eq!(iter.next(), Some(vec!["A", "B"])); 168 | assert_eq!(iter.next(), Some(vec!["A", "B", "C"])); 169 | assert_eq!(iter.next(), Some(vec!["A", "B", "D"])); 170 | assert_eq!(iter.next(), Some(vec!["A", "B", "D", "E"])); 171 | assert_eq!(iter.next(), Some(vec!["A", "F"])); 172 | assert_eq!(iter.next(), Some(vec!["A", "F", "G"])); 173 | assert_eq!(iter.next(), Some(vec!["A", "F", "G", "H"])); 174 | assert_eq!(iter.next(), Some(vec!["A", "F", "I"])); 175 | assert_eq!(iter.next(), None); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/dft_post.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::iter::FusedIterator; 3 | 4 | /// [Depth-First Traversal] in Post-Order. 5 | /// 6 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 7 | /// 8 | /// # Cycles 9 | /// 10 | /// `DftPost` does not handle cycles. If any 11 | /// cycles are present, then `DftPost` will 12 | /// result in an infinite (never ending) 13 | /// [`Iterator`]. 14 | /// 15 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 16 | /// 17 | /// # Example 18 | /// 19 | /// ``` 20 | /// use traversal::DftPost; 21 | /// 22 | /// struct Node(&'static str, &'static [Node]); 23 | /// 24 | /// let tree = Node("G", &[ 25 | /// Node("C", &[ 26 | /// Node("A", &[]), 27 | /// Node("B", &[]) 28 | /// ]), 29 | /// Node("F", &[ 30 | /// Node("D", &[]), 31 | /// Node("E", &[]) 32 | /// ]), 33 | /// ]); 34 | /// 35 | /// // `&tree` represents the root `Node`. 36 | /// // The `FnMut(&Node) -> Iterator` returns 37 | /// // an `Iterator` to get the child `Node`s. 38 | /// let iter = DftPost::new(&tree, |node| node.1.iter()); 39 | /// 40 | /// // Map `Iterator` into `Iterator` 41 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 42 | /// 43 | /// assert_eq!(iter.next(), Some((2, "A"))); 44 | /// assert_eq!(iter.next(), Some((2, "B"))); 45 | /// assert_eq!(iter.next(), Some((1, "C"))); 46 | /// assert_eq!(iter.next(), Some((2, "D"))); 47 | /// assert_eq!(iter.next(), Some((2, "E"))); 48 | /// assert_eq!(iter.next(), Some((1, "F"))); 49 | /// assert_eq!(iter.next(), Some((0, "G"))); 50 | /// assert_eq!(iter.next(), None); 51 | /// ``` 52 | #[allow(missing_debug_implementations)] 53 | #[derive(Clone)] 54 | pub struct DftPost<'a, T, F, I> 55 | where 56 | T: ?Sized, 57 | F: FnMut(&'a T) -> I, 58 | I: Iterator, 59 | { 60 | /// `iter_children(self.queue[i])` has been called for all `i < visited` 61 | visited: usize, 62 | current_depth: usize, 63 | queue: VecDeque<(usize, &'a T)>, 64 | iter_children: F, 65 | } 66 | 67 | impl<'a, T, F, I> DftPost<'a, T, F, I> 68 | where 69 | T: ?Sized, 70 | F: FnMut(&'a T) -> I, 71 | I: Iterator, 72 | { 73 | /// Creates a `DftPost`, where `root` is the 74 | /// starting `Node`. 75 | /// 76 | /// The `iter_children` [`FnMut`] is (lazily) called 77 | /// for each `Node` as needed, where the 78 | /// returned [`Iterator`] produces the child 79 | /// `Node`s for the given `Node`. 80 | /// 81 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 82 | /// 83 | /// *[See `DftPost` for more information.][`DftPost`]* 84 | /// 85 | /// [`DftPost`]: struct.DftPost.html 86 | /// 87 | /// # "`FnOnce`" 88 | /// 89 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 90 | /// a `Node`, as `iter_children` is at most called once for 91 | /// each individual `Node`. 92 | /// 93 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 94 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 95 | /// 96 | /// # `FusedIterator` 97 | /// 98 | /// While `DftPost` does not require [`FusedIterator`], 99 | /// it assumes that no `Node`s are produced after 100 | /// a `None`. 101 | /// 102 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 103 | #[inline] 104 | pub fn new(root: &'a T, iter_children: F) -> Self { 105 | Self { 106 | visited: 0, 107 | current_depth: 0, 108 | queue: VecDeque::from(vec![(0, root)]), 109 | iter_children, 110 | } 111 | } 112 | } 113 | 114 | impl<'a, T, F, I> Iterator for DftPost<'a, T, F, I> 115 | where 116 | T: ?Sized, 117 | F: FnMut(&'a T) -> I, 118 | I: Iterator, 119 | { 120 | type Item = (usize, &'a T); 121 | 122 | #[inline] 123 | fn next(&mut self) -> Option { 124 | if self.queue.is_empty() { 125 | None 126 | } else { 127 | // Exhaust all children for the first branch 128 | loop { 129 | let i = self.visited; 130 | let (depth, node) = if let Some(&node) = self.queue.get(i) { 131 | node 132 | } else { 133 | break; 134 | }; 135 | 136 | // This node is not a child nor a sibling 137 | if self.current_depth > depth { 138 | break; 139 | } 140 | 141 | let before_len = self.queue.len(); 142 | 143 | for (j, child) in (self.iter_children)(node).enumerate() { 144 | self.queue.insert(i + j + 1, (depth + 1, child)); 145 | } 146 | self.visited += 1; 147 | 148 | self.current_depth = depth; 149 | 150 | // The previous node produced no children 151 | if self.queue.len() == before_len { 152 | break; 153 | } 154 | } 155 | 156 | let node = self.queue.remove(self.visited - 1).unwrap(); 157 | self.visited -= 1; 158 | 159 | self.current_depth = node.0; 160 | 161 | Some(node) 162 | } 163 | } 164 | } 165 | 166 | impl<'a, T, F, I> FusedIterator for DftPost<'a, T, F, I> 167 | where 168 | T: ?Sized, 169 | F: FnMut(&'a T) -> I, 170 | I: Iterator, 171 | { 172 | } 173 | 174 | #[cfg(test)] 175 | mod tests { 176 | use super::*; 177 | 178 | struct Node(&'static str, &'static [Node]); 179 | 180 | #[test] 181 | fn dft_post() { 182 | #[rustfmt::skip] 183 | let tree = Node("I", &[ 184 | Node("D", &[ 185 | Node("A", &[]), 186 | Node("C", &[ 187 | Node("B", &[]) 188 | ])]), 189 | Node("H", &[ 190 | Node("F", &[ 191 | Node("E", &[]) 192 | ]), 193 | Node("G", &[])]), 194 | ]); 195 | 196 | let iter = DftPost::new(&tree, |node| node.1.iter()); 197 | let mut iter = iter.map(|(depth, node)| (depth, node.0)); 198 | 199 | assert_eq!(iter.next(), Some((2, "A"))); 200 | assert_eq!(iter.next(), Some((3, "B"))); 201 | assert_eq!(iter.next(), Some((2, "C"))); 202 | assert_eq!(iter.next(), Some((1, "D"))); 203 | assert_eq!(iter.next(), Some((3, "E"))); 204 | assert_eq!(iter.next(), Some((2, "F"))); 205 | assert_eq!(iter.next(), Some((2, "G"))); 206 | assert_eq!(iter.next(), Some((1, "H"))); 207 | assert_eq!(iter.next(), Some((0, "I"))); 208 | assert_eq!(iter.next(), None); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/dft_post_rev.rs: -------------------------------------------------------------------------------- 1 | use std::iter::{Extend, FusedIterator}; 2 | 3 | /// Reverse [Depth-First Traversal] in Post-Order. 4 | /// 5 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 6 | /// 7 | /// # Cycles 8 | /// 9 | /// `DftPostRev` does not handle cycles. If any 10 | /// cycles are present, then `DftPostRev` will 11 | /// result in an infinite (never ending) 12 | /// [`Iterator`]. 13 | /// 14 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 15 | /// 16 | /// # Example 17 | /// 18 | /// ``` 19 | /// use traversal::DftPostRev; 20 | /// 21 | /// struct Node(&'static str, &'static [Node]); 22 | /// 23 | /// let tree = Node("A", &[ 24 | /// Node("E", &[ 25 | /// Node("G", &[]), 26 | /// Node("F", &[]) 27 | /// ]), 28 | /// Node("B", &[ 29 | /// Node("D", &[]), 30 | /// Node("C", &[]) 31 | /// ]), 32 | /// ]); 33 | /// 34 | /// // `&tree` represents the root `Node`. 35 | /// // The `FnMut(&Node) -> Iterator` returns 36 | /// // an `Iterator` to get the child `Node`s. 37 | /// let iter = DftPostRev::new(&tree, |node| node.1.iter()); 38 | /// 39 | /// // Map `Iterator` into `Iterator` 40 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 41 | /// 42 | /// assert_eq!(iter.next(), Some((0, "A"))); 43 | /// assert_eq!(iter.next(), Some((1, "B"))); 44 | /// assert_eq!(iter.next(), Some((2, "C"))); 45 | /// assert_eq!(iter.next(), Some((2, "D"))); 46 | /// assert_eq!(iter.next(), Some((1, "E"))); 47 | /// assert_eq!(iter.next(), Some((2, "F"))); 48 | /// assert_eq!(iter.next(), Some((2, "G"))); 49 | /// assert_eq!(iter.next(), None); 50 | /// ``` 51 | #[allow(missing_debug_implementations)] 52 | #[derive(Clone)] 53 | pub struct DftPostRev<'a, T, F, I> 54 | where 55 | T: ?Sized, 56 | F: FnMut(&'a T) -> I, 57 | I: Iterator, 58 | { 59 | queue: Vec<(usize, &'a T)>, 60 | iter_children: F, 61 | } 62 | 63 | impl<'a, T, F, I> DftPostRev<'a, T, F, I> 64 | where 65 | T: ?Sized, 66 | F: FnMut(&'a T) -> I, 67 | I: Iterator, 68 | { 69 | /// Creates a `DftPostRev`, where `root` is the 70 | /// starting `Node`. 71 | /// 72 | /// The `iter_children` [`FnMut`] is (lazily) called 73 | /// for each `Node` as needed, where the 74 | /// returned [`Iterator`] produces the child 75 | /// `Node`s for the given `Node`. 76 | /// 77 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 78 | /// 79 | /// *[See `DftPostRev` for more information.][`DftPostRev`]* 80 | /// 81 | /// [`DftPostRev`]: struct.DftPostRev.html 82 | /// 83 | /// # "`FnOnce`" 84 | /// 85 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 86 | /// a `Node`, as `iter_children` is at most called once for 87 | /// each individual `Node`. 88 | /// 89 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 90 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 91 | /// 92 | /// # `FusedIterator` 93 | /// 94 | /// While `DftPostRev` does not require [`FusedIterator`], 95 | /// it assumes that no `Node`s are produced after 96 | /// a `None`. 97 | /// 98 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 99 | #[inline] 100 | pub fn new(root: &'a T, iter_children: F) -> Self { 101 | Self { 102 | queue: vec![(0, root)], 103 | iter_children, 104 | } 105 | } 106 | } 107 | 108 | impl<'a, T, F, I> Iterator for DftPostRev<'a, T, F, I> 109 | where 110 | T: ?Sized, 111 | F: FnMut(&'a T) -> I, 112 | I: Iterator, 113 | { 114 | type Item = (usize, &'a T); 115 | 116 | fn next(&mut self) -> Option { 117 | if let Some((depth, node)) = self.queue.pop() { 118 | let children = (self.iter_children)(node); 119 | self.queue.extend(children.map(|child| (depth + 1, child))); 120 | 121 | Some((depth, node)) 122 | } else { 123 | None 124 | } 125 | } 126 | } 127 | 128 | impl<'a, T, F, I> FusedIterator for DftPostRev<'a, T, F, I> 129 | where 130 | T: ?Sized, 131 | F: FnMut(&'a T) -> I, 132 | I: Iterator, 133 | { 134 | } 135 | 136 | #[cfg(test)] 137 | mod tests { 138 | use crate::DftPost; 139 | 140 | use super::*; 141 | 142 | #[derive(PartialEq, Debug)] 143 | struct Node(&'static str, &'static [Node]); 144 | 145 | #[rustfmt::skip] 146 | const TREE: Node = Node("A", &[ 147 | Node("F", &[ 148 | Node("I", &[]), 149 | Node("G", &[ 150 | Node("H", &[]) 151 | ])]), 152 | Node("B", &[ 153 | Node("D", &[ 154 | Node("E", &[]) 155 | ]), 156 | Node("C", &[])]), 157 | ]); 158 | 159 | #[test] 160 | fn dft_post_rev() { 161 | let iter = DftPostRev::new(&TREE, |node| node.1.iter()); 162 | let mut iter = iter.map(|(depth, node)| (depth, node.0)); 163 | 164 | assert_eq!(iter.next(), Some((0, "A"))); 165 | assert_eq!(iter.next(), Some((1, "B"))); 166 | assert_eq!(iter.next(), Some((2, "C"))); 167 | assert_eq!(iter.next(), Some((2, "D"))); 168 | assert_eq!(iter.next(), Some((3, "E"))); 169 | assert_eq!(iter.next(), Some((1, "F"))); 170 | assert_eq!(iter.next(), Some((2, "G"))); 171 | assert_eq!(iter.next(), Some((3, "H"))); 172 | assert_eq!(iter.next(), Some((2, "I"))); 173 | assert_eq!(iter.next(), None); 174 | } 175 | 176 | #[test] 177 | fn dft_post() { 178 | let mut iter1 = DftPostRev::new(&TREE, |node| node.1.iter()); 179 | 180 | let iter2 = DftPost::new(&TREE, |node| node.1.iter()).collect::>(); 181 | let mut iter2 = iter2.into_iter().rev(); 182 | 183 | loop { 184 | let next1 = iter1.next(); 185 | let next2 = iter2.next(); 186 | 187 | if next1.is_none() && next2.is_none() { 188 | break; 189 | } 190 | 191 | assert_eq!(next1, next2); 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/dft_pre.rs: -------------------------------------------------------------------------------- 1 | use std::iter::{Extend, FusedIterator}; 2 | 3 | /// [Depth-First Traversal] in Pre-Order. 4 | /// 5 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 6 | /// 7 | /// # Cycles 8 | /// 9 | /// `DftPre` does not handle cycles. If any 10 | /// cycles are present, then `DftPre` will 11 | /// result in an infinite (never ending) 12 | /// [`Iterator`]. 13 | /// 14 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 15 | /// 16 | /// # Example 17 | /// 18 | /// ``` 19 | /// use traversal::DftPre; 20 | /// 21 | /// struct Node(&'static str, &'static [Node]); 22 | /// 23 | /// let tree = Node("A", &[ 24 | /// Node("B", &[ 25 | /// Node("C", &[]), 26 | /// Node("D", &[]) 27 | /// ]), 28 | /// Node("E", &[ 29 | /// Node("F", &[]), 30 | /// Node("G", &[]) 31 | /// ]), 32 | /// ]); 33 | /// 34 | /// // `&tree` represents the root `Node`. 35 | /// // The `FnMut(&Node) -> Iterator` returns 36 | /// // an `Iterator` to get the child `Node`s. 37 | /// let iter = DftPre::new(&tree, |node| node.1.iter()); 38 | /// 39 | /// // Map `Iterator` into `Iterator` 40 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 41 | /// 42 | /// assert_eq!(iter.next(), Some((0, "A"))); 43 | /// assert_eq!(iter.next(), Some((1, "B"))); 44 | /// assert_eq!(iter.next(), Some((2, "C"))); 45 | /// assert_eq!(iter.next(), Some((2, "D"))); 46 | /// assert_eq!(iter.next(), Some((1, "E"))); 47 | /// assert_eq!(iter.next(), Some((2, "F"))); 48 | /// assert_eq!(iter.next(), Some((2, "G"))); 49 | /// assert_eq!(iter.next(), None); 50 | /// ``` 51 | #[allow(missing_debug_implementations)] 52 | #[derive(Clone)] 53 | pub struct DftPre<'a, T, F, I> 54 | where 55 | T: ?Sized, 56 | F: FnMut(&'a T) -> I, 57 | I: Iterator, 58 | { 59 | queue: Vec<(usize, &'a T)>, 60 | iter_children: F, 61 | } 62 | 63 | impl<'a, T, F, I> DftPre<'a, T, F, I> 64 | where 65 | T: ?Sized, 66 | F: FnMut(&'a T) -> I, 67 | I: Iterator, 68 | { 69 | /// Creates a `DftPre`, where `root` is the 70 | /// starting `Node`. 71 | /// 72 | /// The `iter_children` [`FnMut`] is (lazily) called 73 | /// for each `Node` as needed, where the 74 | /// returned [`Iterator`] produces the child 75 | /// `Node`s for the given `Node`. 76 | /// 77 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 78 | /// 79 | /// *[See `DftPre` for more information.][`DftPre`]* 80 | /// 81 | /// [`DftPre`]: struct.DftPre.html 82 | /// 83 | /// # "`FnOnce`" 84 | /// 85 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 86 | /// a `Node`, as `iter_children` is at most called once for 87 | /// each individual `Node`. 88 | /// 89 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 90 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 91 | /// 92 | /// # `FusedIterator` 93 | /// 94 | /// While `DftPre` does not require [`FusedIterator`], 95 | /// it assumes that no `Node`s are produced after 96 | /// a `None`. 97 | /// 98 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 99 | #[inline] 100 | pub fn new(root: &'a T, iter_children: F) -> Self { 101 | Self { 102 | queue: vec![(0, root)], 103 | iter_children, 104 | } 105 | } 106 | } 107 | 108 | impl<'a, T, F, I> Iterator for DftPre<'a, T, F, I> 109 | where 110 | T: ?Sized, 111 | F: FnMut(&'a T) -> I, 112 | I: Iterator, 113 | { 114 | type Item = (usize, &'a T); 115 | 116 | #[inline] 117 | fn next(&mut self) -> Option { 118 | if let Some((depth, node)) = self.queue.pop() { 119 | let children = (self.iter_children)(node); 120 | 121 | let children = children.collect::>(); 122 | let children = children.into_iter().rev(); 123 | 124 | self.queue.extend(children.map(|child| (depth + 1, child))); 125 | 126 | Some((depth, node)) 127 | } else { 128 | None 129 | } 130 | } 131 | } 132 | 133 | impl<'a, T, F, I> FusedIterator for DftPre<'a, T, F, I> 134 | where 135 | T: ?Sized, 136 | F: FnMut(&'a T) -> I, 137 | I: Iterator, 138 | { 139 | } 140 | 141 | #[cfg(test)] 142 | mod tests { 143 | use std::slice::Iter; 144 | 145 | use super::*; 146 | 147 | struct Node(&'static str, &'static [Node]); 148 | 149 | trait NodeNoSize<'a, T: 'a> { 150 | type Iter: Iterator; 151 | 152 | fn title(&self) -> &'static str; 153 | fn iter_children(&self) -> Self::Iter; 154 | } 155 | 156 | impl<'a> NodeNoSize<'a, Node> for Node { 157 | type Iter = Iter<'a, Self>; 158 | 159 | #[inline] 160 | fn title(&self) -> &'static str { 161 | self.0 162 | } 163 | 164 | #[inline] 165 | fn iter_children(&self) -> Self::Iter { 166 | self.1.iter() 167 | } 168 | } 169 | 170 | #[rustfmt::skip] 171 | const TREE: Node = Node("A", &[ 172 | Node("B", &[ 173 | Node("C", &[]), 174 | Node("D", &[ 175 | Node("E", &[]) 176 | ])]), 177 | Node("F", &[ 178 | Node("G", &[ 179 | Node("H", &[]) 180 | ]), 181 | Node("I", &[])]), 182 | ]); 183 | 184 | #[test] 185 | fn dft_pre() { 186 | let iter = DftPre::new(&TREE, |node| node.1.iter()); 187 | let mut iter = iter.map(|(depth, node)| (depth, node.0)); 188 | 189 | assert_eq!(iter.next(), Some((0, "A"))); 190 | assert_eq!(iter.next(), Some((1, "B"))); 191 | assert_eq!(iter.next(), Some((2, "C"))); 192 | assert_eq!(iter.next(), Some((2, "D"))); 193 | assert_eq!(iter.next(), Some((3, "E"))); 194 | assert_eq!(iter.next(), Some((1, "F"))); 195 | assert_eq!(iter.next(), Some((2, "G"))); 196 | assert_eq!(iter.next(), Some((3, "H"))); 197 | assert_eq!(iter.next(), Some((2, "I"))); 198 | assert_eq!(iter.next(), None); 199 | } 200 | 201 | #[test] 202 | fn dft_pre_no_size() { 203 | let root: &dyn NodeNoSize> = &TREE; 204 | 205 | let iter = DftPre::new(root, |node| { 206 | node.iter_children() 207 | .map(|node| node as &dyn NodeNoSize>) 208 | }); 209 | let mut iter = iter.map(|(depth, node)| (depth, node.title())); 210 | 211 | assert_eq!(iter.next(), Some((0, "A"))); 212 | assert_eq!(iter.next(), Some((1, "B"))); 213 | assert_eq!(iter.next(), Some((2, "C"))); 214 | assert_eq!(iter.next(), Some((2, "D"))); 215 | assert_eq!(iter.next(), Some((3, "E"))); 216 | assert_eq!(iter.next(), Some((1, "F"))); 217 | assert_eq!(iter.next(), Some((2, "G"))); 218 | assert_eq!(iter.next(), Some((3, "H"))); 219 | assert_eq!(iter.next(), Some((2, "I"))); 220 | assert_eq!(iter.next(), None); 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /src/dft_pre_rev.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::iter::FusedIterator; 3 | 4 | /// Reverse [Depth-First Traversal] in Pre-Order. 5 | /// 6 | /// [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 7 | /// 8 | /// # Cycles 9 | /// 10 | /// `DftPreRev` does not handle cycles. If any 11 | /// cycles are present, then `DftPreRev` will 12 | /// result in an infinite (never ending) 13 | /// [`Iterator`]. 14 | /// 15 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 16 | /// 17 | /// # Example 18 | /// 19 | /// ``` 20 | /// use traversal::DftPreRev; 21 | /// 22 | /// struct Node(&'static str, &'static [Node]); 23 | /// 24 | /// let tree = Node("G", &[ 25 | /// Node("F", &[ 26 | /// Node("E", &[]), 27 | /// Node("D", &[]) 28 | /// ]), 29 | /// Node("C", &[ 30 | /// Node("B", &[]), 31 | /// Node("A", &[]) 32 | /// ]), 33 | /// ]); 34 | /// 35 | /// // `&tree` represents the root `Node`. 36 | /// // The `FnMut(&Node) -> Iterator` returns 37 | /// // an `Iterator` to get the child `Node`s. 38 | /// let iter = DftPreRev::new(&tree, |node| node.1.iter()); 39 | /// 40 | /// // Map `Iterator` into `Iterator` 41 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 42 | /// 43 | /// assert_eq!(iter.next(), Some((2, "A"))); 44 | /// assert_eq!(iter.next(), Some((2, "B"))); 45 | /// assert_eq!(iter.next(), Some((1, "C"))); 46 | /// assert_eq!(iter.next(), Some((2, "D"))); 47 | /// assert_eq!(iter.next(), Some((2, "E"))); 48 | /// assert_eq!(iter.next(), Some((1, "F"))); 49 | /// assert_eq!(iter.next(), Some((0, "G"))); 50 | /// assert_eq!(iter.next(), None); 51 | /// ``` 52 | #[allow(missing_debug_implementations)] 53 | #[derive(Clone)] 54 | pub struct DftPreRev<'a, T, F, I> 55 | where 56 | T: ?Sized, 57 | F: FnMut(&'a T) -> I, 58 | I: Iterator, 59 | { 60 | /// `iter_children(self.queue[i])` has been called for all `i < visited` 61 | visited: usize, 62 | current_depth: usize, 63 | queue: VecDeque<(usize, &'a T)>, 64 | iter_children: F, 65 | } 66 | 67 | impl<'a, T, F, I> DftPreRev<'a, T, F, I> 68 | where 69 | T: ?Sized, 70 | F: FnMut(&'a T) -> I, 71 | I: Iterator, 72 | { 73 | /// Creates a `DftPreRev`, where `root` is the 74 | /// starting `Node`. 75 | /// 76 | /// The `iter_children` [`FnMut`] is (lazily) called 77 | /// for each `Node` as needed, where the 78 | /// returned [`Iterator`] produces the child 79 | /// `Node`s for the given `Node`. 80 | /// 81 | /// [`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html 82 | /// 83 | /// *[See `DftPreRev` for more information.][`DftPreRev`]* 84 | /// 85 | /// [`DftPreRev`]: struct.DftPreRev.html 86 | /// 87 | /// # "`FnOnce`" 88 | /// 89 | /// The [`FnMut`] is a [`FnOnce`] from the point-of-view of 90 | /// a `Node`, as `iter_children` is at most called once for 91 | /// each individual `Node`. 92 | /// 93 | /// [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 94 | /// [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 95 | /// 96 | /// # `FusedIterator` 97 | /// 98 | /// While `DftPreRev` does not require [`FusedIterator`], 99 | /// it assumes that no `Node`s are produced after 100 | /// a `None`. 101 | /// 102 | /// [`FusedIterator`]: https://doc.rust-lang.org/stable/std/iter/trait.FusedIterator.html 103 | #[inline] 104 | pub fn new(root: &'a T, iter_children: F) -> Self { 105 | Self { 106 | visited: 0, 107 | current_depth: 0, 108 | queue: VecDeque::from(vec![(0, root)]), 109 | iter_children, 110 | } 111 | } 112 | } 113 | 114 | impl<'a, T, F, I> Iterator for DftPreRev<'a, T, F, I> 115 | where 116 | T: ?Sized, 117 | F: FnMut(&'a T) -> I, 118 | I: Iterator, 119 | { 120 | type Item = (usize, &'a T); 121 | 122 | #[inline] 123 | fn next(&mut self) -> Option { 124 | if self.queue.is_empty() { 125 | None 126 | } else { 127 | // Exhaust all children for the first branch 128 | loop { 129 | let i = self.visited; 130 | let (depth, node) = if let Some(&node) = self.queue.get(i) { 131 | node 132 | } else { 133 | break; 134 | }; 135 | 136 | // This node is not a child nor a sibling 137 | if self.current_depth > depth { 138 | break; 139 | } 140 | 141 | let before_len = self.queue.len(); 142 | 143 | for child in (self.iter_children)(node) { 144 | self.queue.insert(i + 1, (depth + 1, child)); 145 | } 146 | self.visited += 1; 147 | 148 | self.current_depth = depth; 149 | 150 | // The previous node produced no children 151 | if self.queue.len() == before_len { 152 | break; 153 | } 154 | } 155 | 156 | let node = self.queue.remove(self.visited - 1).unwrap(); 157 | self.visited -= 1; 158 | 159 | self.current_depth = node.0; 160 | 161 | Some(node) 162 | } 163 | } 164 | } 165 | 166 | impl<'a, T, F, I> FusedIterator for DftPreRev<'a, T, F, I> 167 | where 168 | T: ?Sized, 169 | F: FnMut(&'a T) -> I, 170 | I: Iterator, 171 | { 172 | } 173 | 174 | #[cfg(test)] 175 | mod tests { 176 | use crate::DftPre; 177 | 178 | use super::*; 179 | 180 | #[derive(PartialEq, Debug)] 181 | struct Node(&'static str, &'static [Node]); 182 | 183 | #[rustfmt::skip] 184 | const TREE: Node = Node("I", &[ 185 | Node("H", &[ 186 | Node("G", &[]), 187 | Node("F", &[ 188 | Node("E", &[]) 189 | ])]), 190 | Node("D", &[ 191 | Node("C", &[ 192 | Node("B", &[]) 193 | ]), 194 | Node("A", &[])]), 195 | ]); 196 | 197 | #[test] 198 | fn dft_pre_rev() { 199 | let iter = DftPreRev::new(&TREE, |node| node.1.iter()); 200 | let mut iter = iter.map(|(depth, node)| (depth, node.0)); 201 | 202 | assert_eq!(iter.next(), Some((2, "A"))); 203 | assert_eq!(iter.next(), Some((3, "B"))); 204 | assert_eq!(iter.next(), Some((2, "C"))); 205 | assert_eq!(iter.next(), Some((1, "D"))); 206 | assert_eq!(iter.next(), Some((3, "E"))); 207 | assert_eq!(iter.next(), Some((2, "F"))); 208 | assert_eq!(iter.next(), Some((2, "G"))); 209 | assert_eq!(iter.next(), Some((1, "H"))); 210 | assert_eq!(iter.next(), Some((0, "I"))); 211 | assert_eq!(iter.next(), None); 212 | } 213 | 214 | #[test] 215 | fn dft_pre() { 216 | let mut iter1 = DftPreRev::new(&TREE, |node| node.1.iter()); 217 | 218 | let iter2 = DftPre::new(&TREE, |node| node.1.iter()).collect::>(); 219 | let mut iter2 = iter2.into_iter().rev(); 220 | 221 | loop { 222 | let next1 = iter1.next(); 223 | let next2 = iter2.next(); 224 | 225 | if next1.is_none() && next2.is_none() { 226 | break; 227 | } 228 | 229 | assert_eq!(next1, next2); 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Traversal implements generic and lazy tree traversal algorithms. 2 | //! 3 | //! Includes: 4 | //! - [Breadth-First Traversal] ([`Bft`]) 5 | //! - [Depth-First Traversal] in Pre-Order ([`DftPre`]) 6 | //! - [Depth-First Traversal] in Post-Order ([`DftPost`]) 7 | //! - Reverse [Depth-First Traversal] in Pre-Order ([`DftPreRev`]) 8 | //! - Reverse [Depth-First Traversal] in Post-Order ([`DftPostRev`]) 9 | //! 10 | //! - All Paths ([`DftPaths`]) 11 | //! - Longest Paths ([`DftLongestPaths`]) 12 | //! - All Cycles (Paths) ([`DftCycles`]) 13 | //! 14 | //! [Breadth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 15 | //! [Depth-First Traversal]: https://en.wikipedia.org/wiki/Tree_traversal 16 | //! 17 | //! ## Generic 18 | //! 19 | //! Traversal uses [generics] (or [type parameters]) to be 20 | //! flexible to use, and easy to implement and fit into existing 21 | //! architecture. 22 | //! 23 | //! [generics]: https://doc.rust-lang.org/rust-by-example/generics.html 24 | //! [type parameters]: https://doc.rust-lang.org/reference/types/parameters.html 25 | //! 26 | //! ## Laziness 27 | //! 28 | //! Laziness or [lazy evaluation] refers to evaluation being delayed 29 | //! until needed. 30 | //! 31 | //! Traversal delays processing `Node`s and fetching child `Node`s 32 | //! until [`Iterator::next`][`next`] is called. 33 | //! When [`next`] is called, then traversal only processes the 34 | //! `Node`s required for this iteration. 35 | //! 36 | //! [lazy evaluation]: https://en.wikipedia.org/wiki/Lazy_evaluation 37 | //! 38 | //! *From Rust's docs:* 39 | //! 40 | //! > *Iterators (and iterator [adapters]) are lazy. This means that just 41 | //! > creating an iterator doesn't do a whole lot. Nothing really happens 42 | //! > until you call [`next`].* 43 | //! > 44 | //! > — [`Iterator`] - [Laziness] 45 | //! 46 | //! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 47 | //! [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next 48 | //! 49 | //! [Laziness]: https://doc.rust-lang.org/std/iter/index.html#laziness 50 | //! [adapters]: https://doc.rust-lang.org/std/iter/index.html#adapters 51 | //! 52 | //! # Algorithms 53 | //! 54 | //! ```text 55 | //! A 56 | //! / \ 57 | //! B C 58 | //! / \ / \ 59 | //! D E F G 60 | //! ``` 61 | //! 62 | //! Given the above tree, then the following are the orders, 63 | //! that each individual iterator / traversal algorithm produces. 64 | //! 65 | //! | Algorithm | Order | 66 | //! |-----------|-------| 67 | //! | [`Bft`] (Breadth-First Traversal) | A, B, C, D, E, F, G | 68 | //! | [`DftPre`] (Depth-First Traversal in Pre-Order) | A, B, D, E, C, F, G | 69 | //! | [`DftPost`] (Depth-First Traversal in Post-Order) | D, E, B, F, G, C, A | 70 | //! | [`DftPreRev`] (Reverse Depth-First Traversal in Pre-Order) | G, F, C, E, D, B, A | 71 | //! | [`DftPostRev`] (Reverse Depth-First Traversal in Post-Order) | A, C, G, F, B, E, D | 72 | //! 73 | //! *See each individual algorithm for code examples.* 74 | //! 75 | //! [`Bft`]: struct.Bft.html 76 | //! [`DftPre`]: struct.DftPre.html 77 | //! [`DftPost`]: struct.DftPost.html 78 | //! [`DftPreRev`]: struct.DftPreRev.html 79 | //! [`DftPostRev`]: struct.DftPostRev.html 80 | //! 81 | //! ## All Paths and Longest Paths 82 | //! 83 | //! [`DftPaths`] and [`DftLongestPaths`] are utilities for 84 | //! iterating all paths and the longest paths in a tree. 85 | //! 86 | //! *Given the same tree as the previous examples, then 87 | //! [`DftPaths`] and [`DftLongestPaths`] produce the 88 | //! following paths.* 89 | //! 90 | //! [`DftPaths`]: 91 | //! - A, B 92 | //! - A, B, D 93 | //! - A, B, E 94 | //! - A, C 95 | //! - A, C, F 96 | //! - A, C, G 97 | //! 98 | //! [`DftLongestPaths`]: 99 | //! - A, B, D 100 | //! - A, B, E 101 | //! - A, C, F 102 | //! - A, C, G 103 | //! 104 | //! *See each individual algorithm for code examples.* 105 | //! 106 | //! [`DftPaths`]: struct.DftPaths.html 107 | //! [`DftLongestPaths`]: struct.DftLongestPaths.html 108 | //! 109 | //! ## Cycles 110 | //! 111 | //! ```text 112 | //! A <---+ 113 | //! / \ | 114 | //! B D >-+ 115 | //! | | | 116 | //! C E >-+ 117 | //! ``` 118 | //! 119 | //! [`DftCycles`]: 120 | //! - A -> D (*implies D is connected with A*) 121 | //! - A -> D -> E 122 | //! 123 | //! *See each individual algorithm for code examples.* 124 | //! 125 | //! [`DftCycles`]: struct.DftCycles.html 126 | 127 | #![forbid(unsafe_code)] 128 | #![deny(missing_docs)] 129 | #![deny(missing_debug_implementations)] 130 | #![warn(clippy::all)] 131 | 132 | mod bft; 133 | mod dft_cycles; 134 | mod dft_longest_paths; 135 | mod dft_paths; 136 | mod dft_post; 137 | mod dft_post_rev; 138 | mod dft_pre; 139 | mod dft_pre_rev; 140 | 141 | pub use bft::*; 142 | pub use dft_cycles::*; 143 | pub use dft_longest_paths::*; 144 | pub use dft_paths::*; 145 | pub use dft_post::*; 146 | pub use dft_post_rev::*; 147 | pub use dft_pre::*; 148 | pub use dft_pre_rev::*; 149 | 150 | use std::hash::Hash; 151 | 152 | /// *[This is a shorthand for `Bft::new`, see `Bft` for more information.][`Bft`]* 153 | /// 154 | /// [`Bft`]: struct.Bft.html 155 | /// 156 | /// # Example 157 | /// 158 | /// ``` 159 | /// struct Node(&'static str, &'static [Node]); 160 | /// 161 | /// let tree = Node("A", &[ 162 | /// Node("B", &[ 163 | /// Node("D", &[]), 164 | /// Node("E", &[]) 165 | /// ]), 166 | /// Node("C", &[ 167 | /// Node("F", &[]), 168 | /// Node("G", &[]) 169 | /// ]), 170 | /// ]); 171 | /// 172 | /// // `&tree` represents the root `Node`. 173 | /// // The `FnMut(&Node) -> Iterator` returns 174 | /// // an `Iterator` to get the child `Node`s. 175 | /// let iter = traversal::bft(&tree, |node| node.1.iter()); 176 | /// 177 | /// // Map `Iterator` into `Iterator` 178 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 179 | /// 180 | /// assert_eq!(iter.next(), Some((0, "A"))); 181 | /// assert_eq!(iter.next(), Some((1, "B"))); 182 | /// assert_eq!(iter.next(), Some((1, "C"))); 183 | /// assert_eq!(iter.next(), Some((2, "D"))); 184 | /// assert_eq!(iter.next(), Some((2, "E"))); 185 | /// assert_eq!(iter.next(), Some((2, "F"))); 186 | /// assert_eq!(iter.next(), Some((2, "G"))); 187 | /// assert_eq!(iter.next(), None); 188 | /// ``` 189 | #[inline] 190 | pub fn bft<'a, T, F, I>(root: &'a T, iter_children: F) -> Bft<'a, T, F, I> 191 | where 192 | T: ?Sized, 193 | F: FnMut(&'a T) -> I, 194 | I: Iterator, 195 | { 196 | Bft::new(root, iter_children) 197 | } 198 | 199 | /// *[This is a shorthand for `DftPre::new`, see `DftPre` for more information.][`DftPre`]* 200 | /// 201 | /// [`DftPre`]: struct.DftPre.html 202 | /// 203 | /// # Example 204 | /// 205 | /// ``` 206 | /// struct Node(&'static str, &'static [Node]); 207 | /// 208 | /// let tree = Node("A", &[ 209 | /// Node("B", &[ 210 | /// Node("C", &[]), 211 | /// Node("D", &[]) 212 | /// ]), 213 | /// Node("E", &[ 214 | /// Node("F", &[]), 215 | /// Node("G", &[]) 216 | /// ]), 217 | /// ]); 218 | /// 219 | /// // `&tree` represents the root `Node`. 220 | /// // The `FnMut(&Node) -> Iterator` returns 221 | /// // an `Iterator` to get the child `Node`s. 222 | /// let iter = traversal::dft_pre(&tree, |node| node.1.iter()); 223 | /// 224 | /// // Map `Iterator` into `Iterator` 225 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 226 | /// 227 | /// assert_eq!(iter.next(), Some((0, "A"))); 228 | /// assert_eq!(iter.next(), Some((1, "B"))); 229 | /// assert_eq!(iter.next(), Some((2, "C"))); 230 | /// assert_eq!(iter.next(), Some((2, "D"))); 231 | /// assert_eq!(iter.next(), Some((1, "E"))); 232 | /// assert_eq!(iter.next(), Some((2, "F"))); 233 | /// assert_eq!(iter.next(), Some((2, "G"))); 234 | /// assert_eq!(iter.next(), None); 235 | /// ``` 236 | #[inline] 237 | pub fn dft_pre<'a, T, F, I>(root: &'a T, iter_children: F) -> DftPre<'a, T, F, I> 238 | where 239 | T: ?Sized, 240 | F: FnMut(&'a T) -> I, 241 | I: Iterator, 242 | { 243 | DftPre::new(root, iter_children) 244 | } 245 | 246 | /// *[This is a shorthand for `DftPost::new`, see `DftPost` for more information.][`DftPost`]* 247 | /// 248 | /// [`DftPost`]: struct.DftPost.html 249 | /// 250 | /// # Example 251 | /// 252 | /// ``` 253 | /// struct Node(&'static str, &'static [Node]); 254 | /// 255 | /// let tree = Node("G", &[ 256 | /// Node("C", &[ 257 | /// Node("A", &[]), 258 | /// Node("B", &[]) 259 | /// ]), 260 | /// Node("F", &[ 261 | /// Node("D", &[]), 262 | /// Node("E", &[]) 263 | /// ]), 264 | /// ]); 265 | /// 266 | /// // `&tree` represents the root `Node`. 267 | /// // The `FnMut(&Node) -> Iterator` returns 268 | /// // an `Iterator` to get the child `Node`s. 269 | /// let iter = traversal::dft_post(&tree, |node| node.1.iter()); 270 | /// 271 | /// // Map `Iterator` into `Iterator` 272 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 273 | /// 274 | /// assert_eq!(iter.next(), Some((2, "A"))); 275 | /// assert_eq!(iter.next(), Some((2, "B"))); 276 | /// assert_eq!(iter.next(), Some((1, "C"))); 277 | /// assert_eq!(iter.next(), Some((2, "D"))); 278 | /// assert_eq!(iter.next(), Some((2, "E"))); 279 | /// assert_eq!(iter.next(), Some((1, "F"))); 280 | /// assert_eq!(iter.next(), Some((0, "G"))); 281 | /// assert_eq!(iter.next(), None); 282 | /// ``` 283 | #[inline] 284 | pub fn dft_post<'a, T, F, I>(root: &'a T, iter_children: F) -> DftPost<'a, T, F, I> 285 | where 286 | T: ?Sized, 287 | F: FnMut(&'a T) -> I, 288 | I: Iterator, 289 | { 290 | DftPost::new(root, iter_children) 291 | } 292 | 293 | /// *[This is a shorthand for `DftPreRev::new`, see `DftPreRev` for more information.][`DftPreRev`]* 294 | /// 295 | /// [`DftPreRev`]: struct.DftPreRev.html 296 | /// 297 | /// 298 | /// # Example 299 | /// 300 | /// ``` 301 | /// struct Node(&'static str, &'static [Node]); 302 | /// 303 | /// let tree = Node("G", &[ 304 | /// Node("F", &[ 305 | /// Node("E", &[]), 306 | /// Node("D", &[]) 307 | /// ]), 308 | /// Node("C", &[ 309 | /// Node("B", &[]), 310 | /// Node("A", &[]) 311 | /// ]), 312 | /// ]); 313 | /// 314 | /// // `&tree` represents the root `Node`. 315 | /// // The `FnMut(&Node) -> Iterator` returns 316 | /// // an `Iterator` to get the child `Node`s. 317 | /// let iter = traversal::dft_pre_rev(&tree, |node| node.1.iter()); 318 | /// 319 | /// // Map `Iterator` into `Iterator` 320 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 321 | /// 322 | /// assert_eq!(iter.next(), Some((2, "A"))); 323 | /// assert_eq!(iter.next(), Some((2, "B"))); 324 | /// assert_eq!(iter.next(), Some((1, "C"))); 325 | /// assert_eq!(iter.next(), Some((2, "D"))); 326 | /// assert_eq!(iter.next(), Some((2, "E"))); 327 | /// assert_eq!(iter.next(), Some((1, "F"))); 328 | /// assert_eq!(iter.next(), Some((0, "G"))); 329 | /// assert_eq!(iter.next(), None); 330 | /// ``` 331 | #[inline] 332 | pub fn dft_pre_rev<'a, T, F, I>(root: &'a T, iter_children: F) -> DftPreRev<'a, T, F, I> 333 | where 334 | T: ?Sized, 335 | F: FnMut(&'a T) -> I, 336 | I: Iterator, 337 | { 338 | DftPreRev::new(root, iter_children) 339 | } 340 | 341 | /// *[This is a shorthand for `DftPostRev::new`, see `DftPostRev` for more information.][`DftPostRev`]* 342 | /// 343 | /// [`DftPostRev`]: struct.DftPostRev.html 344 | /// 345 | /// # Example 346 | /// 347 | /// ``` 348 | /// struct Node(&'static str, &'static [Node]); 349 | /// 350 | /// let tree = Node("A", &[ 351 | /// Node("E", &[ 352 | /// Node("G", &[]), 353 | /// Node("F", &[]) 354 | /// ]), 355 | /// Node("B", &[ 356 | /// Node("D", &[]), 357 | /// Node("C", &[]) 358 | /// ]), 359 | /// ]); 360 | /// 361 | /// // `&tree` represents the root `Node`. 362 | /// // The `FnMut(&Node) -> Iterator` returns 363 | /// // an `Iterator` to get the child `Node`s. 364 | /// let iter = traversal::dft_post_rev(&tree, |node| node.1.iter()); 365 | /// 366 | /// // Map `Iterator` into `Iterator` 367 | /// let mut iter = iter.map(|(depth, node)| (depth, node.0)); 368 | /// 369 | /// assert_eq!(iter.next(), Some((0, "A"))); 370 | /// assert_eq!(iter.next(), Some((1, "B"))); 371 | /// assert_eq!(iter.next(), Some((2, "C"))); 372 | /// assert_eq!(iter.next(), Some((2, "D"))); 373 | /// assert_eq!(iter.next(), Some((1, "E"))); 374 | /// assert_eq!(iter.next(), Some((2, "F"))); 375 | /// assert_eq!(iter.next(), Some((2, "G"))); 376 | /// assert_eq!(iter.next(), None); 377 | /// ``` 378 | #[inline] 379 | pub fn dft_post_rev<'a, T, F, I>(root: &'a T, iter_children: F) -> DftPostRev<'a, T, F, I> 380 | where 381 | T: ?Sized, 382 | F: FnMut(&'a T) -> I, 383 | I: Iterator, 384 | { 385 | DftPostRev::new(root, iter_children) 386 | } 387 | 388 | /// *[This is a shorthand for `DftPaths::new`, see `DftPaths` for more information.][`DftPaths`]* 389 | /// 390 | /// [`DftPaths`]: struct.DftPaths.html 391 | /// 392 | /// # Example 393 | /// 394 | /// ``` 395 | /// struct Node(&'static str, &'static [Node]); 396 | /// 397 | /// let tree = Node("A", &[ 398 | /// Node("B", &[ 399 | /// Node("C", &[]), 400 | /// Node("D", &[]) 401 | /// ]), 402 | /// Node("E", &[ 403 | /// Node("F", &[]), 404 | /// Node("G", &[]) 405 | /// ]), 406 | /// ]); 407 | /// 408 | /// // `&tree` represents the root `Node`. 409 | /// // The `FnMut(&Node) -> Iterator` returns 410 | /// // an `Iterator` to get the child `Node`s. 411 | /// let iter = traversal::dft_paths(&tree, |node| node.1.iter()); 412 | /// 413 | /// // Map `Iterator>` into `Iterator>` 414 | /// let mut iter = iter.map(|path| path.iter().map(|node| node.0).collect::>()); 415 | /// 416 | /// assert_eq!(iter.next(), Some(vec!["A", "B"])); 417 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "C"])); 418 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "D"])); 419 | /// assert_eq!(iter.next(), Some(vec!["A", "E"])); 420 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "F"])); 421 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "G"])); 422 | /// assert_eq!(iter.next(), None); 423 | /// ``` 424 | #[inline] 425 | pub fn dft_paths<'a, T, F, I>(root: &'a T, iter_children: F) -> DftPaths<'a, T, F, I> 426 | where 427 | T: ?Sized, 428 | F: FnMut(&'a T) -> I, 429 | I: Iterator, 430 | { 431 | DftPaths::new(root, iter_children) 432 | } 433 | 434 | /// *[This is a shorthand for `DftLongestPaths::new`, see `DftLongestPaths` for more information.][`DftLongestPaths`]* 435 | /// 436 | /// [`DftLongestPaths`]: struct.DftLongestPaths.html 437 | /// 438 | /// # Example 439 | /// 440 | /// ``` 441 | /// struct Node(&'static str, &'static [Node]); 442 | /// 443 | /// let tree = Node("A", &[ 444 | /// Node("B", &[ 445 | /// Node("C", &[]), 446 | /// Node("D", &[]) 447 | /// ]), 448 | /// Node("E", &[ 449 | /// Node("F", &[]), 450 | /// Node("G", &[]) 451 | /// ]), 452 | /// ]); 453 | /// 454 | /// // `&tree` represents the root `Node`. 455 | /// // The `FnMut(&Node) -> Iterator` returns 456 | /// // an `Iterator` to get the child `Node`s. 457 | /// let iter = traversal::dft_longest_paths(&tree, |node| node.1.iter()); 458 | /// 459 | /// // Map `Iterator>` into `Iterator>` 460 | /// let mut iter = iter.map(|path| path.iter().map(|node| node.0).collect::>()); 461 | /// 462 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "C"])); 463 | /// assert_eq!(iter.next(), Some(vec!["A", "B", "D"])); 464 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "F"])); 465 | /// assert_eq!(iter.next(), Some(vec!["A", "E", "G"])); 466 | /// assert_eq!(iter.next(), None); 467 | /// ``` 468 | #[inline] 469 | pub fn dft_longest_paths<'a, T, F, I>(root: &'a T, iter_children: F) -> DftLongestPaths<'a, T, F, I> 470 | where 471 | T: ?Sized, 472 | F: FnMut(&'a T) -> I, 473 | I: Iterator, 474 | { 475 | DftLongestPaths::new(root, iter_children) 476 | } 477 | 478 | /// *[This is a shorthand for `DftCycles::new`, see `DftCycles` for more information.][`DftCycles`]* 479 | /// 480 | /// [`DftCycles`]: struct.DftCycles.html 481 | /// 482 | /// # Example 483 | /// 484 | /// ``` 485 | /// #[derive(PartialEq, Eq, Hash)] 486 | /// struct Vertex(&'static str, Vec); 487 | /// 488 | /// // A <-+ 489 | /// // /|\ | 490 | /// // B | C | 491 | /// // \|/ | 492 | /// // D >-+ 493 | /// // 494 | /// // Cycles: 495 | /// // - A -> B -> D -> A 496 | /// // - A -> D -> A 497 | /// // - A -> C -> D -> A 498 | /// let graph = vec![ 499 | /// Vertex("A", vec![1, 3, 2]), // 0 500 | /// Vertex("B", vec![3]), // 1 501 | /// Vertex("C", vec![3]), // 2 502 | /// Vertex("D", vec![0]), // 3 503 | /// ]; 504 | /// 505 | /// let start = &graph[0]; // A 506 | /// 507 | /// // `&tree` represents the root `Vertex`. 508 | /// // The `FnMut(&Vertex) -> Iterator` returns 509 | /// // an `Iterator` to get the connected vertices. 510 | /// let mut cycles = traversal::dft_cycles(start, |vertex| { 511 | /// vertex.1.iter().map(|&i| { 512 | /// &graph[i] 513 | /// }) 514 | /// }); 515 | /// 516 | /// // Map `Iterator>` into `Iterator>` 517 | /// let mut cycles = cycles.map(|path| path.iter().map(|vertex| vertex.0).collect::>()); 518 | /// 519 | /// assert_eq!(cycles.next(), Some(vec!["A", "B", "D"])); 520 | /// assert_eq!(cycles.next(), Some(vec!["A", "D"])); 521 | /// assert_eq!(cycles.next(), Some(vec!["A", "C", "D"])); 522 | /// assert_eq!(cycles.next(), None); 523 | /// ``` 524 | #[inline] 525 | pub fn dft_cycles<'a, T, F, I>(root: &'a T, iter_children: F) -> DftCycles<'a, T, F, I> 526 | where 527 | T: ?Sized, 528 | F: FnMut(&'a T) -> I, 529 | I: Iterator, 530 | T: Eq + Hash, 531 | { 532 | DftCycles::new(root, iter_children) 533 | } 534 | 535 | #[cfg(test)] 536 | mod tests { 537 | use super::*; 538 | 539 | #[derive(PartialEq, Eq, Hash)] 540 | struct Vertex(&'static str, Vec); 541 | 542 | struct Node(&'static str, &'static [Node]); 543 | 544 | #[rustfmt::skip] 545 | const TREE: Node = Node("A", &[ 546 | Node("B", &[ 547 | Node("D", &[]), 548 | Node("E", &[]) 549 | ]), 550 | Node("C", &[ 551 | Node("F", &[]), 552 | Node("G", &[]) 553 | ]), 554 | ]); 555 | 556 | #[test] 557 | fn lib_example() { 558 | // If this example is changed, then update 559 | // both code and output in lib.rs and README.md. 560 | 561 | assert_eq!( 562 | bft(&TREE, |node| node.1.iter()) 563 | .map(|(_, node)| node.0) 564 | .collect::>(), 565 | vec!["A", "B", "C", "D", "E", "F", "G"], 566 | ); 567 | 568 | assert_eq!( 569 | dft_pre(&TREE, |node| node.1.iter()) 570 | .map(|(_, node)| node.0) 571 | .collect::>(), 572 | vec!["A", "B", "D", "E", "C", "F", "G"], 573 | ); 574 | 575 | assert_eq!( 576 | dft_post(&TREE, |node| node.1.iter()) 577 | .map(|(_, node)| node.0) 578 | .collect::>(), 579 | vec!["D", "E", "B", "F", "G", "C", "A"], 580 | ); 581 | 582 | assert_eq!( 583 | dft_pre_rev(&TREE, |node| node.1.iter()) 584 | .map(|(_, node)| node.0) 585 | .collect::>(), 586 | vec!["G", "F", "C", "E", "D", "B", "A"], 587 | ); 588 | 589 | assert_eq!( 590 | dft_post_rev(&TREE, |node| node.1.iter()) 591 | .map(|(_, node)| node.0) 592 | .collect::>(), 593 | vec!["A", "C", "G", "F", "B", "E", "D"], 594 | ); 595 | } 596 | 597 | #[test] 598 | fn lib_example_paths() { 599 | // If this example is changed, then update 600 | // both code and output in lib.rs and README.md. 601 | 602 | assert_eq!( 603 | DftPaths::new(&TREE, |node| node.1.iter()) 604 | .map(|path| path.iter().map(|node| node.0).collect::>()) 605 | .collect::>(), 606 | vec![ 607 | vec!["A", "B"], 608 | vec!["A", "B", "D"], 609 | vec!["A", "B", "E"], 610 | vec!["A", "C"], 611 | vec!["A", "C", "F"], 612 | vec!["A", "C", "G"], 613 | ], 614 | ); 615 | 616 | assert_eq!( 617 | DftLongestPaths::new(&TREE, |node| node.1.iter()) 618 | .map(|path| path.iter().map(|node| node.0).collect::>()) 619 | .collect::>(), 620 | vec![ 621 | vec!["A", "B", "D"], 622 | vec!["A", "B", "E"], 623 | vec!["A", "C", "F"], 624 | vec!["A", "C", "G"], 625 | ], 626 | ); 627 | } 628 | 629 | #[test] 630 | fn lib_example_cycles() { 631 | // If this example is changed, then update 632 | // both code and output in lib.rs and README.md. 633 | 634 | // A <---+ 635 | // / \ | 636 | // B D >-+ 637 | // | | | 638 | // C E >-+ 639 | // 640 | // Cycles: 641 | // - A -> D -> A 642 | // - A -> D -> E -> A 643 | let graph = vec![ 644 | Vertex("A", vec![1, 3]), // 0 645 | Vertex("B", vec![2]), // 1 646 | Vertex("C", vec![]), // 2 647 | Vertex("D", vec![0, 4]), // 3 648 | Vertex("E", vec![0]), // 4 649 | ]; 650 | 651 | let start = &graph[0]; // A 652 | 653 | let cycles = DftCycles::new(start, |vertex| vertex.1.iter().map(|&i| &graph[i])); 654 | let mut cycles = cycles.map(|path| path.iter().map(|vertex| vertex.0).collect::>()); 655 | 656 | assert_eq!(cycles.next(), Some(vec!["A", "D"])); 657 | assert_eq!(cycles.next(), Some(vec!["A", "D", "E"])); 658 | assert_eq!(cycles.next(), None); 659 | } 660 | } 661 | --------------------------------------------------------------------------------