深度优先搜索
use std::collections::HashSet;
use std::collections::VecDeque;
// Perform a Depth First Search Algorithm to find a element in a graph
//
// Return a Optional with a vector with history of vertex visiteds
// or a None if the element not exists on the graph
pub fn depth_first_search(graph: &Graph, root: Vertex, objective: Vertex) -> Option<Vec<u32>> {
let mut visited: HashSet<Vertex> = HashSet::new();
let mut history: Vec<u32> = Vec::new();
let mut queue = VecDeque::new();
queue.push_back(root);
// While there is an element in the queue
// get the first element of the vertex queue
while let Some(current_vertex) = queue.pop_front() {
// Added current vertex in the history of visiteds vertex
history.push(current_vertex.value());
// Verify if this vertex is the objective
if current_vertex == objective {
// Return the Optional with the history of visiteds vertex
return Some(history);
}
// For each over the neighbors of current vertex
for neighbor in current_vertex.neighbors(graph).into_iter().rev() {
// Insert in the HashSet of visiteds if this value not exist yet
if visited.insert(neighbor) {
// Add the neighbor on front of queue
queue.push_front(neighbor);
}
}
}
// If all vertex is visited and the objective is not found
// return a Optional with None value
None
}
// Data Structures
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Vertex(u32);
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Edge(u32, u32);
#[derive(Clone)]
pub struct Graph {
vertices: Vec<Vertex>,
edges: Vec<Edge>,
}
impl Graph {
pub fn new(vertices: Vec<Vertex>, edges: Vec<Edge>) -> Self {
Graph { vertices, edges }
}
}
impl From<u32> for Vertex {
fn from(item: u32) -> Self {
Vertex(item)
}
}
impl Vertex {
pub fn value(&self) -> u32 {
self.0
}
pub fn neighbors(&self, graph: &Graph) -> VecDeque<Vertex> {
graph
.edges
.iter()
.filter(|e| e.0 == self.0)
.map(|e| e.1.into())
.collect()
}
}
impl From<(u32, u32)> for Edge {
fn from(item: (u32, u32)) -> Self {
Edge(item.0, item.1)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn find_1_fail() {
let vertices = vec![1, 2, 3, 4, 5, 6, 7];
let edges = vec![(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7)];
let root = 1;
let objective = 99;
let graph = Graph::new(
vertices.into_iter().map(|v| v.into()).collect(),
edges.into_iter().map(|e| e.into()).collect(),
);
assert_eq!(
depth_first_search(&graph, root.into(), objective.into()),
None
);
}
#[test]
fn find_1_sucess() {
let vertices = vec![1, 2, 3, 4, 5, 6, 7];
let edges = vec![(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7)];
let root = 1;
let objective = 7;
let correct_path = vec![1, 2, 4, 5, 3, 6, 7];
let graph = Graph::new(
vertices.into_iter().map(|v| v.into()).collect(),
edges.into_iter().map(|e| e.into()).collect(),
);
assert_eq!(
depth_first_search(&graph, root.into(), objective.into()),
Some(correct_path)
);
}
#[test]
fn find_2_sucess() {
let vertices = vec![0, 1, 2, 3, 4, 5, 6, 7];
let edges = vec![
(0, 1),
(1, 3),
(3, 2),
(2, 1),
(3, 4),
(4, 5),
(5, 7),
(7, 6),
(6, 4),
];
let root = 0;
let objective = 6;
let correct_path = vec![0, 1, 3, 2, 4, 5, 7, 6];
let graph = Graph::new(
vertices.into_iter().map(|v| v.into()).collect(),
edges.into_iter().map(|e| e.into()).collect(),
);
assert_eq!(
depth_first_search(&graph, root.into(), objective.into()),
Some(correct_path)
);
}
#[test]
fn find_3_sucess() {
let vertices = vec![0, 1, 2, 3, 4, 5, 6, 7];
let edges = vec![
(0, 1),
(1, 3),
(3, 2),
(2, 1),
(3, 4),
(4, 5),
(5, 7),
(7, 6),
(6, 4),
];
let root = 0;
let objective = 4;
let correct_path = vec![0, 1, 3, 2, 4];
let graph = Graph::new(
vertices.into_iter().map(|v| v.into()).collect(),
edges.into_iter().map(|e| e.into()).collect(),
);
assert_eq!(
depth_first_search(&graph, root.into(), objective.into()),
Some(correct_path)
);
}
}
当前内容版权归 rustlang-cn 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 rustlang-cn .