add graph! macro and vertex/edge_count
This commit is contained in:
parent
925370481c
commit
14a3342f60
34
src/graph.rs
34
src/graph.rs
@ -4,7 +4,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub struct Graph<V> {
|
pub struct Graph<V> {
|
||||||
pub vertices: Vec<V>,
|
pub vertices: HashSet<V>,
|
||||||
pub edges: HashMap<V, Vec<V>>,
|
pub edges: HashMap<V, Vec<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,6 +12,16 @@ impl<V> Graph<V>
|
|||||||
where
|
where
|
||||||
V: Eq + Hash + Ord + Clone,
|
V: Eq + Hash + Ord + Clone,
|
||||||
{
|
{
|
||||||
|
/// get the number of vertices of the graph
|
||||||
|
pub fn vertex_count(&self) -> usize {
|
||||||
|
self.vertices.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get the number of edges of the graph
|
||||||
|
pub fn edge_count(&self) -> usize {
|
||||||
|
self.edges.values().map(Vec::len).sum()
|
||||||
|
}
|
||||||
|
|
||||||
/// check if an edge is contained in the graph
|
/// check if an edge is contained in the graph
|
||||||
/// (only checks the provided direction)
|
/// (only checks the provided direction)
|
||||||
pub fn has_edge(&self, edge: (&V, &V)) -> bool {
|
pub fn has_edge(&self, edge: (&V, &V)) -> bool {
|
||||||
@ -49,8 +59,7 @@ where
|
|||||||
q.push_back(vec![from]);
|
q.push_back(vec![from]);
|
||||||
visited.insert(from);
|
visited.insert(from);
|
||||||
|
|
||||||
while !q.is_empty() {
|
while let Some(mut path) = q.pop_front() {
|
||||||
let mut path = q.pop_front().unwrap();
|
|
||||||
let current = path.last().unwrap();
|
let current = path.last().unwrap();
|
||||||
|
|
||||||
for neighbor in self.neighbors(current) {
|
for neighbor in self.neighbors(current) {
|
||||||
@ -81,8 +90,7 @@ where
|
|||||||
|
|
||||||
q.push(vec![from]);
|
q.push(vec![from]);
|
||||||
|
|
||||||
while !q.is_empty() {
|
while let Some(mut path) = q.pop() {
|
||||||
let mut path = q.pop().unwrap();
|
|
||||||
let ¤t = path.last().unwrap();
|
let ¤t = path.last().unwrap();
|
||||||
|
|
||||||
if current == to {
|
if current == to {
|
||||||
@ -103,3 +111,19 @@ where
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! graph {
|
||||||
|
( $( $v:tt : $( $e:tt ),* );* $(;)? ) => {{
|
||||||
|
let mut edges = std::collections::HashMap::new();
|
||||||
|
let mut vertices = std::collections::HashSet::new();
|
||||||
|
|
||||||
|
$(
|
||||||
|
vertices.insert($v);
|
||||||
|
edges.insert($v, vec![$( $e ),*]);
|
||||||
|
$( vertices.insert($e); )*
|
||||||
|
)*
|
||||||
|
|
||||||
|
Graph { vertices, edges }
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|||||||
42
src/main.rs
42
src/main.rs
@ -1,5 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
mod graph;
|
mod graph;
|
||||||
pub use graph::Graph;
|
pub use graph::Graph;
|
||||||
|
|
||||||
@ -9,24 +7,18 @@ fn main() {
|
|||||||
// -> 0 ┃ 3
|
// -> 0 ┃ 3
|
||||||
// ┗━━━━━2━━━━━┛
|
// ┗━━━━━2━━━━━┛
|
||||||
|
|
||||||
let vs = vec![0, 1, 2, 3];
|
let g = graph! {
|
||||||
let es = HashMap::from([
|
0: 1, 2;
|
||||||
(0, vec![1, 2]),
|
1: 0, 2, 3;
|
||||||
(1, vec![0, 2, 3]),
|
2: 0, 1, 3;
|
||||||
(2, vec![0, 1, 3]),
|
3: 1, 2;
|
||||||
(3, vec![1, 2]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
let g = Graph {
|
|
||||||
vertices: vs.clone(),
|
|
||||||
edges: es.clone(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for v in &vs {
|
for v in &g.vertices {
|
||||||
assert!(g.has_vertex(v), "G should contain vertex {v}");
|
assert!(g.has_vertex(v), "G should contain vertex {v}");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (a, neighbors) in &es {
|
for (a, neighbors) in &g.edges {
|
||||||
for b in neighbors {
|
for b in neighbors {
|
||||||
assert!(g.has_edge((a, b)), "G should contain edge ({a}, {b})");
|
assert!(g.has_edge((a, b)), "G should contain edge ({a}, {b})");
|
||||||
assert!(
|
assert!(
|
||||||
@ -36,19 +28,27 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..vs.len() {
|
let n = g.vertex_count();
|
||||||
for j in i + 1..vs.len() {
|
let vs = g.vertices.iter().collect::<Vec<_>>();
|
||||||
|
for i in 0..n {
|
||||||
|
for j in i + 1..n {
|
||||||
let (a, b) = (vs[i], vs[j]);
|
let (a, b) = (vs[i], vs[j]);
|
||||||
let shortest_path_length = match (a, b) {
|
let shortest_path_length = match (a, b) {
|
||||||
(0, 3) | (3, 0) => 3,
|
(0, 3) | (3, 0) => 3,
|
||||||
_ => 2,
|
_ => 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = g.find_path_dfs(&a, &b);
|
let path = g.find_path_dfs(a, b);
|
||||||
assert!(path.is_some(), "Path from {a} to {b} should be found in G with dfs");
|
assert!(
|
||||||
|
path.is_some(),
|
||||||
|
"Path from {a} to {b} should be found in G with dfs"
|
||||||
|
);
|
||||||
|
|
||||||
let path = g.find_path_bfs(&a, &b);
|
let path = g.find_path_bfs(a, b);
|
||||||
assert!(path.is_some(), "Path from {a} to {b} should be found in G with bfs");
|
assert!(
|
||||||
|
path.is_some(),
|
||||||
|
"Path from {a} to {b} should be found in G with bfs"
|
||||||
|
);
|
||||||
|
|
||||||
let path = path.unwrap();
|
let path = path.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user