sim_lib_discrete_graph/
traversal.rs1use crate::error::GraphError;
4use crate::graph::Graph;
5use std::collections::VecDeque;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Traversal {
10 pub order: Vec<usize>,
12 pub predecessor: Vec<Option<usize>>,
15}
16
17fn check_start<N, W>(graph: &Graph<N, W>, start: usize) -> Result<(), GraphError> {
18 if start >= graph.node_count() {
19 return Err(GraphError::NodeOutOfRange {
20 node: start,
21 count: graph.node_count(),
22 });
23 }
24 Ok(())
25}
26
27pub fn bfs<N, W>(graph: &Graph<N, W>, start: usize) -> Result<Traversal, GraphError> {
47 check_start(graph, start)?;
48 let n = graph.node_count();
49 let mut visited = vec![false; n];
50 let mut predecessor = vec![None; n];
51 let mut order = Vec::new();
52 let mut queue = VecDeque::new();
53 visited[start] = true;
54 queue.push_back(start);
55 while let Some(u) = queue.pop_front() {
56 order.push(u);
57 for adj in graph.neighbors(u)? {
58 if !visited[adj.node] {
59 visited[adj.node] = true;
60 predecessor[adj.node] = Some(u);
61 queue.push_back(adj.node);
62 }
63 }
64 }
65 Ok(Traversal { order, predecessor })
66}
67
68pub fn dfs<N, W>(graph: &Graph<N, W>, start: usize) -> Result<Traversal, GraphError> {
71 check_start(graph, start)?;
72 let n = graph.node_count();
73 let mut visited = vec![false; n];
74 let mut predecessor = vec![None; n];
75 let mut order = Vec::new();
76 let mut stack = vec![(start, None)];
79 while let Some((u, pred)) = stack.pop() {
80 if visited[u] {
81 continue;
82 }
83 visited[u] = true;
84 predecessor[u] = pred;
85 order.push(u);
86 let neighbors = graph.neighbors(u)?;
87 for adj in neighbors.into_iter().rev() {
88 if !visited[adj.node] {
89 stack.push((adj.node, Some(u)));
90 }
91 }
92 }
93 Ok(Traversal { order, predecessor })
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use crate::edge::Directedness;
100
101 fn diamond() -> Graph<u8, u64> {
102 let mut g = Graph::with_nodes(vec![0, 1, 2, 3], Directedness::Undirected);
104 g.add_edge(0, 1, 1).unwrap();
105 g.add_edge(0, 2, 1).unwrap();
106 g.add_edge(1, 3, 1).unwrap();
107 g.add_edge(2, 3, 1).unwrap();
108 g
109 }
110
111 #[test]
112 fn bfs_is_deterministic() {
113 let t = bfs(&diamond(), 0).unwrap();
114 assert_eq!(t.order, vec![0, 1, 2, 3]);
115 assert_eq!(t.predecessor[3], Some(1)); }
117
118 #[test]
119 fn dfs_is_deterministic() {
120 let t = dfs(&diamond(), 0).unwrap();
121 assert_eq!(t.order, vec![0, 1, 3, 2]);
122 }
123
124 #[test]
125 fn bad_start_fails() {
126 assert!(matches!(
127 bfs(&diamond(), 9),
128 Err(GraphError::NodeOutOfRange { node: 9, .. })
129 ));
130 }
131}