aboutsummaryrefslogtreecommitdiff
path: root/graph/src/dfs.rs
blob: e9af3deeebc1a651d210f4e8e9e68025f4a277b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! This module implements a function to produce the depth-first order
//! for a graph.

use super::*;

use error::Error;

/// Return a list of indices that are ordered according to a depth-first search.
///
/// A node is only recorded at most once.  And the search starts from
/// the `root`, so this in fact only includes the connected component
/// of the `root`.
pub fn dfs(g: &impl Graph, root: usize) -> Result<Vec<usize>, Error> {
    // let g = g.borrow();

    let nodes_len = g.nodes_len();

    let mut result: Vec<usize> = Vec::with_capacity(nodes_len);

    let mut stack: Vec<usize> = Vec::with_capacity(nodes_len);

    stack.push(root);

    let mut seen_nodes: Vec<bool> = std::iter::repeat(false).take(nodes_len).collect();

    while let Some(top) = stack.pop() {
        match seen_nodes.get_mut(top) {
            Some(reference) if !*reference => {
                *reference = true;

                result.push(top);

                // REVIEW: Maybe I shall add a method
                // `children_of_rev`.

                stack.extend(g.children_of(top)?.collect::<Vec<_>>().into_iter().rev());
            }
            None => {
                return Err(Error::IndexOutOfBounds(top, nodes_len));
            }
            _ => {}
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::labelled::simple::SLGBuilder;

    #[test]
    fn test_dfs() -> Result<(), Box<dyn std::error::Error>> {
        let mut builder = SLGBuilder::<usize, usize>::default();

        // Add five nodes
        builder.add_vertex(0);
        builder.add_vertex(1);
        builder.add_vertex(2);
        builder.add_vertex(3);
        builder.add_vertex(4);

        let dummy_label = 0usize;

        builder.add_edge(0, 1, dummy_label)?;
        builder.add_edge(0, 4, dummy_label)?;
        builder.add_edge(1, 4, dummy_label)?;
        builder.add_edge(1, 2, dummy_label)?;
        builder.add_edge(2, 3, dummy_label)?;
        builder.add_edge(3, 4, dummy_label)?;

        // build a graph

        let graph = builder.build();

        let dfs = dfs(&graph, 0)?;

        println!("dfs = {dfs:?}");

        let answer = vec![0, 1, 4, 2, 3];

        assert_eq!(answer, dfs);

        Ok(())
    }
}