add graph! macro and vertex/edge_count

This commit is contained in:
mxhagen 2025-02-16 19:25:00 +01:00
parent 925370481c
commit 14a3342f60
2 changed files with 50 additions and 26 deletions

View File

@ -4,7 +4,7 @@ use std::{
};
pub struct Graph<V> {
pub vertices: Vec<V>,
pub vertices: HashSet<V>,
pub edges: HashMap<V, Vec<V>>,
}
@ -12,6 +12,16 @@ impl<V> Graph<V>
where
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
/// (only checks the provided direction)
pub fn has_edge(&self, edge: (&V, &V)) -> bool {
@ -49,8 +59,7 @@ where
q.push_back(vec![from]);
visited.insert(from);
while !q.is_empty() {
let mut path = q.pop_front().unwrap();
while let Some(mut path) = q.pop_front() {
let current = path.last().unwrap();
for neighbor in self.neighbors(current) {
@ -81,8 +90,7 @@ where
q.push(vec![from]);
while !q.is_empty() {
let mut path = q.pop().unwrap();
while let Some(mut path) = q.pop() {
let &current = path.last().unwrap();
if current == to {
@ -103,3 +111,19 @@ where
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 }
}};
}

View File

@ -1,5 +1,3 @@
use std::collections::HashMap;
mod graph;
pub use graph::Graph;
@ -9,24 +7,18 @@ fn main() {
// -> 0 ┃ 3
// ┗━━━━━2━━━━━┛
let vs = vec![0, 1, 2, 3];
let es = HashMap::from([
(0, vec![1, 2]),
(1, vec![0, 2, 3]),
(2, vec![0, 1, 3]),
(3, vec![1, 2]),
]);
let g = Graph {
vertices: vs.clone(),
edges: es.clone(),
let g = graph! {
0: 1, 2;
1: 0, 2, 3;
2: 0, 1, 3;
3: 1, 2;
};
for v in &vs {
for v in &g.vertices {
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 {
assert!(g.has_edge((a, b)), "G should contain edge ({a}, {b})");
assert!(
@ -36,19 +28,27 @@ fn main() {
}
}
for i in 0..vs.len() {
for j in i + 1..vs.len() {
let n = g.vertex_count();
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 shortest_path_length = match (a, b) {
(0, 3) | (3, 0) => 3,
_ => 2,
};
let path = g.find_path_dfs(&a, &b);
assert!(path.is_some(), "Path from {a} to {b} should be found in G with dfs");
let path = g.find_path_dfs(a, b);
assert!(
path.is_some(),
"Path from {a} to {b} should be found in G with dfs"
);
let path = g.find_path_bfs(&a, &b);
assert!(path.is_some(), "Path from {a} to {b} should be found in G with bfs");
let path = g.find_path_bfs(a, b);
assert!(
path.is_some(),
"Path from {a} to {b} should be found in G with bfs"
);
let path = path.unwrap();
assert_eq!(