grafos_tools/algorithms/
breadth_first_search.rs1use crate::{adjacency_list::ToAdjacencyList, Edge, Graph, Vertice};
2use std::{collections::HashSet, fmt::Debug, hash::Hash};
3
4use super::AlgorithmResult;
5
6#[derive(Debug)]
7pub enum BreadthFirstSearchError {
8 FromVerticeNotInGraph,
9 ToVerticeNotInGraph,
10}
11
12pub fn breadth_first_search_queue<G, T, E>(
13 graph: &G,
14 from: &Vertice<T>,
15 to: &Vertice<T>,
16) -> Result<AlgorithmResult<T>, BreadthFirstSearchError>
17where
18 T: PartialOrd + Debug + Clone + Eq + Hash,
19 G: Graph<T, E> + ToAdjacencyList<T>,
20 E: Edge<T>,
21{
22 use super::BreadthFirstSearchError::*;
23
24 let adjacency_list = graph.to_adjacency_list();
25
26 if !graph.vertices().contains(&from) {
28 return Err(FromVerticeNotInGraph);
29 }
30 if !graph.vertices().contains(&to) {
31 return Err(ToVerticeNotInGraph);
32 }
33
34 let mut queue: Vec<Vertice<T>> = Vec::with_capacity(adjacency_list.0.len());
55 queue.push(from.clone());
56 let mut current_index = 0;
57
58 while current_index < adjacency_list.0.len() {
60 let current_vertice = queue
62 .get(current_index)
63 .expect("Vertice not in queue somehow");
64
65 if *current_vertice == *to {
67 break; }
69
70 for neighbor in adjacency_list
72 .0
73 .get(current_vertice)
74 .expect("Vertice not in adjacency list somehow")
75 {
76 queue.push(neighbor.clone());
77 if *neighbor == *to {
79 break;
80 }
81 }
82
83 current_index += 1;
84 }
85
86 let mut last_vertice_in_path = queue
95 .last()
96 .expect("Not last element in queue found")
97 .clone();
98 let mut path: Vec<Vertice<T>> = vec![];
99 let mut current_nearest = last_vertice_in_path.clone();
100
101 for current_vertice in queue.iter().rev() {
103 let is_neighbour_of_last =
104 adjacency_list.check_neighbor_for(&last_vertice_in_path, current_vertice);
105 println!("{:?} is now current nearest", current_vertice);
106
107 if current_vertice == to || current_vertice == from {
108 path.insert(0, current_vertice.clone());
109 } else if is_neighbour_of_last {
110 current_nearest = current_vertice.clone();
111 } else {
112 path.push(current_vertice.clone());
113 last_vertice_in_path = current_nearest.clone()
114 }
115 }
116
117 let mut visited = HashSet::new();
118 queue.iter().for_each(|vertice| {
119 visited.insert(vertice.clone());
120 });
121
122 Ok(AlgorithmResult { path, visited })
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use crate::simple_graph;
129
130 #[test]
131 fn check_two_vertice_simple_graph_path() {
132 let graph = simple_graph::SimpleGraph::new_two();
133
134 let vertices: Vec<&Vertice<usize>> = graph.vertices().iter().collect();
135
136 let from = *vertices.first().unwrap();
137 let to = *vertices.last().unwrap();
138
139 let result = breadth_first_search_queue(&graph, from, to).unwrap();
140
141 println!("from: {from:?} | to {to:?} | result {result:?}");
142
143 assert_eq!(result.path.len(), 2);
144 assert_eq!(result.visited.len(), 2);
145 }
146}