use crate::maps::VertexMap; use crate::traits::GraphTopology; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Vertex(usize); impl From for usize { fn from(v: Vertex) -> usize { v.0 } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Incidence(usize); struct VertexIncidenceHeader { incidence_count: usize, first_incidence: Option, } struct IncidenceEntry { next: Option, neighbor: Vertex, } struct VertexNeighborIterator<'a> { graph: &'a AppendGraph, incidence: Option, } impl<'a> Iterator for VertexNeighborIterator<'a> { type Item = Vertex; fn next(&mut self) -> Option { let incidence = self.incidence?; let entry = &self.graph.incidences[incidence.0]; self.incidence = entry.next; Some(entry.neighbor) } } pub struct AppendGraph { // TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'? vertices: Vec, incidences: Vec, } impl AppendGraph { pub fn new() -> Self { Self { vertices: vec![], incidences: vec![], } } // Adds a single incidence of an edge, which is composed by two such incidences, to the // incidences vector. fn add_incidence(&mut self, v1: Vertex, v2: Vertex) { self.incidences.push(IncidenceEntry { next: self.vertices[v1.0].first_incidence.take(), neighbor: v2, }); self.vertices[v1.0].incidence_count += 1; self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1)); } } impl Default for AppendGraph { fn default() -> Self { Self::new() } } impl GraphTopology for AppendGraph { type Vertex = Vertex; type Edge = Incidence; fn vertex_count(&self) -> usize { self.vertices.len() } fn edge_count(&self) -> usize { self.incidences.len() / 2 } fn vertex_capacity(&self) -> usize { self.vertices.len() } fn vertex_map(&self, default: T) -> VertexMap { VertexMap::new(default, |v| v.0, self.vertex_capacity()) } fn degree(&self, v: Self::Vertex) -> usize { self.vertices[v.0].incidence_count } fn are_adjacent(&self, v1: Self::Vertex, v2: Self::Vertex) -> bool { self.neighbors(v1).any(|x| x == v2) } fn vertices(&self) -> impl Iterator { (0..self.vertices.len()).map(Vertex) } fn neighbors(&self, v: Self::Vertex) -> impl Iterator { VertexNeighborIterator { graph: self, incidence: self.vertices[v.0].first_incidence, } } fn edges(&self) -> impl Iterator { (0..self.incidences.len()).step_by(2).map(Incidence) } fn add_vertex(&mut self) -> Self::Vertex { self.vertices.push(VertexIncidenceHeader { incidence_count: 0, first_incidence: None, }); Vertex(self.vertices.len() - 1) } fn add_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge { self.add_incidence(v1, v2); self.add_incidence(v2, v1); Incidence(self.incidences.len() - 2) } } #[cfg(test)] mod tests { use super::*; crate::graph_topology_test_fixtures!(AppendGraph); crate::graph_topology_tests!(AppendGraph); }