Add GraphTopology.incidence_cursor() for certain use-cases where the iterator is problematic
Also add raw_incidences() and step_incidence() to AppendGraph analogously to Graph, which allows to remove RawIncidenceIterator and simplify its call sites.
This commit is contained in:
+27
-25
@@ -1,5 +1,5 @@
|
||||
use crate::maps::{EdgeMap, VertexMap};
|
||||
use crate::traits::GraphTopology;
|
||||
use crate::traits::{GraphTopology, IncidenceCursor};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Vertex(usize);
|
||||
@@ -18,24 +18,20 @@ struct VertexIncidenceHeader {
|
||||
first_incidence: Option<Incidence>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct IncidenceEntry {
|
||||
next: Option<Incidence>,
|
||||
adjacent: Vertex,
|
||||
}
|
||||
|
||||
struct RawIncidenceIterator<'a> {
|
||||
graph: &'a AppendGraph,
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AppendGraphIncidenceCursor {
|
||||
incidence: Option<Incidence>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for RawIncidenceIterator<'a> {
|
||||
type Item = (Vertex, Incidence);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current = self.incidence?;
|
||||
let entry = &self.graph.incidences[current.0];
|
||||
self.incidence = entry.next;
|
||||
Some((entry.adjacent, current))
|
||||
impl IncidenceCursor<AppendGraph> for AppendGraphIncidenceCursor {
|
||||
fn next(&mut self, graph: &AppendGraph) -> Option<(Vertex, Incidence)> {
|
||||
graph.step_incidence(&mut self.incidence)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +58,18 @@ impl AppendGraph {
|
||||
self.vertices[v1.0].incidence_count += 1;
|
||||
self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1));
|
||||
}
|
||||
|
||||
fn raw_incidences(&self, v: Vertex) -> impl Iterator<Item = (Vertex, Incidence)> {
|
||||
let mut incidence = self.vertices[v.0].first_incidence;
|
||||
std::iter::from_fn(move || self.step_incidence(&mut incidence))
|
||||
}
|
||||
|
||||
fn step_incidence(&self, incidence: &mut Option<Incidence>) -> Option<(Vertex, Incidence)> {
|
||||
let current = (*incidence)?;
|
||||
let entry = self.incidences[current.0];
|
||||
*incidence = entry.next;
|
||||
Some((entry.adjacent, current))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AppendGraph {
|
||||
@@ -72,8 +80,8 @@ impl Default for AppendGraph {
|
||||
|
||||
impl GraphTopology for AppendGraph {
|
||||
type Vertex = Vertex;
|
||||
|
||||
type Edge = Incidence;
|
||||
type IncidenceCursor = AppendGraphIncidenceCursor;
|
||||
|
||||
fn vertex_count(&self) -> usize {
|
||||
self.vertices.len()
|
||||
@@ -112,11 +120,7 @@ impl GraphTopology for AppendGraph {
|
||||
}
|
||||
|
||||
fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex> {
|
||||
RawIncidenceIterator {
|
||||
graph: self,
|
||||
incidence: self.vertices[v.0].first_incidence,
|
||||
}
|
||||
.map(|(v, _)| v)
|
||||
self.raw_incidences(v).map(|(v, _)| v)
|
||||
}
|
||||
|
||||
fn incident_vertices(&self, e: Self::Edge) -> (Self::Vertex, Self::Vertex) {
|
||||
@@ -130,19 +134,17 @@ impl GraphTopology for AppendGraph {
|
||||
}
|
||||
|
||||
fn incident_edges(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Edge> {
|
||||
RawIncidenceIterator {
|
||||
graph: self,
|
||||
incidence: self.vertices[v.0].first_incidence,
|
||||
}
|
||||
.map(|(_, e)| e.normalize())
|
||||
self.raw_incidences(v).map(|(_, e)| e.normalize())
|
||||
}
|
||||
|
||||
fn incidences(&self, v: Self::Vertex) -> impl Iterator<Item = (Self::Vertex, Self::Edge)> {
|
||||
RawIncidenceIterator {
|
||||
graph: self,
|
||||
self.raw_incidences(v).map(|(v, e)| (v, e.normalize()))
|
||||
}
|
||||
|
||||
fn incidence_cursor(&self, v: Self::Vertex) -> Self::IncidenceCursor {
|
||||
AppendGraphIncidenceCursor {
|
||||
incidence: self.vertices[v.0].first_incidence,
|
||||
}
|
||||
.map(|(v, e)| (v, e.normalize()))
|
||||
}
|
||||
|
||||
fn add_vertex(&mut self) -> Self::Vertex {
|
||||
|
||||
Reference in New Issue
Block a user