Add GraphTopology::incidences(), update and add related tests
This commit is contained in:
@@ -7,6 +7,12 @@ pub struct Vertex(usize);
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Incidence(usize);
|
||||
|
||||
impl Incidence {
|
||||
fn normalize(&self) -> Self {
|
||||
Self(self.0 & !1)
|
||||
}
|
||||
}
|
||||
|
||||
struct VertexIncidenceHeader {
|
||||
incidence_count: usize,
|
||||
first_incidence: Option<Incidence>,
|
||||
@@ -26,13 +32,29 @@ impl<'a> Iterator for AdjacentVertexIterator<'a> {
|
||||
type Item = Vertex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let incidence = self.incidence?;
|
||||
let entry = &self.graph.incidences[incidence.0];
|
||||
let current = self.incidence?;
|
||||
let entry = &self.graph.incidences[current.0];
|
||||
self.incidence = entry.next;
|
||||
Some(entry.adjacent)
|
||||
}
|
||||
}
|
||||
|
||||
struct IncidenceIterator<'a> {
|
||||
graph: &'a AppendGraph,
|
||||
incidence: Option<Incidence>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for IncidenceIterator<'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.normalize()))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AppendGraph {
|
||||
// TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'?
|
||||
vertices: Vec<VertexIncidenceHeader>,
|
||||
@@ -117,6 +139,13 @@ impl GraphTopology for AppendGraph {
|
||||
(0..self.incidences.len()).step_by(2).map(Incidence)
|
||||
}
|
||||
|
||||
fn incidences(&self, v: Self::Vertex) -> impl Iterator<Item = (Self::Vertex, Self::Edge)> {
|
||||
IncidenceIterator {
|
||||
graph: self,
|
||||
incidence: self.vertices[v.0].first_incidence,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_vertex(&mut self) -> Self::Vertex {
|
||||
self.vertices.push(VertexIncidenceHeader {
|
||||
incidence_count: 0,
|
||||
|
||||
@@ -70,6 +70,24 @@ impl IncidentEdgeCursor {
|
||||
}
|
||||
}
|
||||
|
||||
struct IncidenceIterator<'a> {
|
||||
graph: &'a Graph,
|
||||
incidence: Option<IncidenceSlot>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for IncidenceIterator<'a> {
|
||||
type Item = (Vertex, Edge);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current = self.incidence?;
|
||||
let e = self.graph.incidences.get_idx(current.0).unwrap();
|
||||
let entry = &self.graph.incidences[e];
|
||||
self.incidence = entry.next;
|
||||
let v = self.graph.vertices.get_idx(entry.adjacent.0).unwrap();
|
||||
Some((v, self.graph.normalize_edge(e)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Graph {
|
||||
// TODO: Arena index and generation types could be externalized to Graph.
|
||||
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
||||
@@ -142,6 +160,10 @@ impl Graph {
|
||||
self.incidences[previous].next = next;
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_edge(&self, e: Edge) -> Edge {
|
||||
self.incidences.get_idx(e.arr_idx() & !1).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Graph {
|
||||
@@ -205,6 +227,13 @@ impl GraphTopology for Graph {
|
||||
.map(|(i, _)| i)
|
||||
}
|
||||
|
||||
fn incidences(&self, v: Self::Vertex) -> impl Iterator<Item = (Self::Vertex, Self::Edge)> {
|
||||
IncidenceIterator {
|
||||
graph: self,
|
||||
incidence: self.vertices[v].first_incidence,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_vertex(&mut self) -> Self::Vertex {
|
||||
self.vertices.insert(VertexIncidenceHeader {
|
||||
incidence_count: 0,
|
||||
|
||||
Reference in New Issue
Block a user