flex_algo/
graph.rs

1use std::fmt::Debug;
2use std::collections::HashSet;
3
4/// Graph data structure
5/// 
6/// This create implements a Graph data structure
7/// 
8#[derive(Debug)]
9pub struct Graph {
10    adjacent_list: Vec<Vec<usize>>,
11    indegree: Vec<usize>,
12    num_nodes: usize,
13}
14
15impl Graph {
16
17    /// Create a new graph with the given routes tuple(current, neighbor) current <--- neighbor
18    /// 
19    /// # Example
20    /// 
21    /// ```
22    /// use flex_algo::Graph;
23    /// 
24    /// let graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
25    /// println!("graph: {:?}", graph);
26    /// ```
27    pub fn new(num_nodes: usize, routes: Vec<(usize, usize)>) -> Self {
28        let mut adjacent_list = vec![Vec::<usize>::new(); num_nodes];
29        let mut indegree = vec![0; num_nodes];
30        for route in routes {
31          let source = route.1;
32          let target = route.0;
33          adjacent_list[source].push(target);
34          indegree[target] += 1;
35        }
36        Graph {
37          adjacent_list,
38          indegree,
39          num_nodes,
40        }
41    }
42
43    /// Breadth First Search algorithm to check if it's an acyclic graph,
44    /// 
45    /// # Example
46    /// 
47    /// ```
48    /// use flex_algo::Graph;
49    /// 
50    /// let graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
51    /// println!("graph: {:?}", graph);
52    /// assert_eq!(graph.is_acyclic_bfs(), true);
53    /// 
54    /// ```
55    pub fn is_acyclic_bfs(&self) -> bool {
56        for v in 0..self.num_nodes {
57            // println!("start: {}", v);
58            let mut queue = Vec::new();
59            let mut seens = HashSet::new();
60            let mut visit = Vec::new();
61            visit.push(v);
62
63            let adjacent = &self.adjacent_list[v];
64            for &neighbor in adjacent {
65                queue.push(neighbor);
66            }
67
68            while queue.len() > 0 {
69                let vertex = queue.pop().unwrap();
70                if vertex == v {
71                  return false;
72                }
73
74                if !seens.contains(&vertex) {
75                    // println!("traverse: {}", vertex);
76                    visit.push(vertex);
77                    seens.insert(vertex);
78                }
79
80                let adjacent = &self.adjacent_list[vertex];
81                for neighbor in adjacent {
82                    if !seens.contains(neighbor) {
83                        queue.push(*neighbor);
84                    }
85                }
86            }
87            // println!("path: {:?}", visit);
88        }
89        true
90    }
91
92    /// Topological Sort algorithm to check if it's an acyclic graph
93    /// 
94    /// # Example
95    /// 
96    /// ```
97    /// use flex_algo::Graph;
98    /// 
99    /// let mut graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
100    /// println!("graph: {:?}", graph);
101    /// assert_eq!(graph.is_acyclic_top_sort(), true);
102    /// 
103    /// ```
104    pub fn is_acyclic_top_sort(&mut self) -> bool {
105        let mut queue = Vec::new();
106        for i in 0..self.num_nodes {
107            if self.indegree[i] == 0 {
108                queue.push(i);
109            }
110        }
111        let mut count = 0;
112        while !queue.is_empty() {
113            let vertex = queue.pop().unwrap();
114            count += 1;
115            let adjacent = &self.adjacent_list[vertex];
116            for &neighbor in adjacent {
117                self.indegree[neighbor] -= 1;
118                if self.indegree[neighbor] == 0 {
119                    queue.push(neighbor);
120                }
121            }
122        }
123        self.num_nodes == count
124    }
125
126    /// Return the path by breadth first search algo for the graph
127    /// 
128    /// # Example
129    /// 
130    /// ```
131    /// use flex_algo::Graph;
132    /// 
133    /// let mut graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
134    /// let visit = graph.breadth_first_search(5);
135    /// assert_eq!(visit, vec![5, 4, 3, 0, 1, 2]);
136    /// 
137    /// ```
138    pub fn breadth_first_search(&self, start: usize) -> Vec<usize> {
139        let mut queue = Vec::new();
140        let mut visit = Vec::new();
141        let mut seens = HashSet::new();
142        queue.push(start);
143
144        while !queue.is_empty() {
145            // println!("queue: {:?}", queue);
146            let vertex = queue.pop().unwrap();
147            if seens.contains(&vertex) {
148                continue;
149            }
150            seens.insert(vertex);
151            visit.push(vertex);
152            let adjacent = &self.adjacent_list[vertex];
153            for neighbor in adjacent {
154                if !seens.contains(neighbor) {
155                    queue.push(*neighbor);
156                }
157            }
158        }
159        visit
160    }
161
162    /// Return the path by depth first search algo for the graph
163    /// 
164    /// # Example
165    /// 
166    /// ```
167    /// use flex_algo::Graph;
168    /// 
169    /// let graph = Graph::new(8, vec![
170    ///     (5, 4), (2, 4), (6, 4), 
171    ///     (7, 5), (0, 2), (1, 2), (3, 6)
172    /// ]);
173    /// let visit = graph.depth_first_search(4);
174    /// 
175    /// assert_eq!(visit, vec![7, 5, 0, 1, 2, 3, 6, 4]);
176    /// ```
177    pub fn depth_first_search(&self, vertex: usize) -> Vec<usize> {
178        let adjacent = &self.adjacent_list[vertex];
179        if adjacent.is_empty() {
180            return vec![vertex];
181        }
182        let mut visit = Vec::new();
183        for &neighbor in adjacent {
184            visit.append(&mut self.depth_first_search(neighbor));
185        }
186        visit.push(vertex);
187        visit
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn test_graph() {
197        let graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
198        println!("graph: {:?}", graph);
199        // panic!();
200    }
201
202    #[test]
203    fn test_is_acyclic_graph() {
204        let graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
205        println!("graph: {:?}", graph);
206        assert_eq!(graph.is_acyclic_bfs(), true);
207        // panic!();
208    }
209
210    #[test]
211    fn test_is_acyclic_top_sort() {
212        let mut graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
213        println!("graph: {:?}", graph);
214        assert_eq!(graph.is_acyclic_top_sort(), true);
215    }
216
217    #[test]
218    fn test_bfs() {
219        let graph = Graph::new(6, vec![(1, 0), (2, 1), (2, 5), (0, 3), (4, 3), (3, 5), (4, 5)]);
220        let visit = graph.breadth_first_search(5);
221        println!("graph: {:?}", graph);
222        println!("bfs: {:?}", visit);
223        assert_eq!(visit, vec![5, 4, 3, 0, 1, 2]);
224    }
225
226    #[test]
227    fn test_dfs() {
228        let graph = Graph::new(8, vec![
229            (5, 4), (2, 4), (6, 4), 
230            (7, 5), (0, 2), (1, 2), (3, 6)
231        ]);
232        let visit = graph.depth_first_search(4);
233        println!("graph: {:?}", graph);
234        println!("dfs: {:?}", visit);
235        assert_eq!(visit, vec![7, 5, 0, 1, 2, 3, 6, 4]);
236    }
237}