Add Graph::delete_edge() implementation
This commit is contained in:
+62
-1
@@ -40,6 +40,22 @@ impl<'a> Iterator for VertexNeighborIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VertexIncidenceIterator<'a> {
|
||||||
|
graph: &'a Graph,
|
||||||
|
incidence: Option<IncidenceSlot>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for VertexIncidenceIterator<'a> {
|
||||||
|
type Item = Edge;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let current = self.incidence?;
|
||||||
|
let index = self.graph.incidences.get_idx(current.0)?;
|
||||||
|
self.incidence = self.graph.incidences[index].next;
|
||||||
|
Some(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Graph {
|
pub struct Graph {
|
||||||
// TODO: Arena index and generation types could be externalized to Graph.
|
// TODO: Arena index and generation types could be externalized to Graph.
|
||||||
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
||||||
@@ -65,6 +81,32 @@ impl Graph {
|
|||||||
self.vertices[v1].first_incidence = Some(IncidenceSlot(edge.arr_idx()));
|
self.vertices[v1].first_incidence = Some(IncidenceSlot(edge.arr_idx()));
|
||||||
edge
|
edge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deletes a single incidence "e" of an edge, which is composed of two such incidences, from the
|
||||||
|
// incidences arena. "next" is the next incidence after "e", both originating at the vertex
|
||||||
|
// "start".
|
||||||
|
fn delete_incidence(&mut self, e: Edge, start: VertexSlot, next: Option<IncidenceSlot>) {
|
||||||
|
let start_vertex = self
|
||||||
|
.vertices
|
||||||
|
.get_idx(start.0)
|
||||||
|
.expect("missing incident neighbor, corrupt internal data state");
|
||||||
|
let vertex_header = &mut self.vertices[start_vertex];
|
||||||
|
vertex_header.incidence_count -= 1;
|
||||||
|
let first = vertex_header
|
||||||
|
.first_incidence
|
||||||
|
.expect("incident neighbor without incidences, corrupt internal data state");
|
||||||
|
if first.0 == e.arr_idx() {
|
||||||
|
vertex_header.first_incidence = next;
|
||||||
|
} else {
|
||||||
|
let previous = VertexIncidenceIterator {
|
||||||
|
graph: self,
|
||||||
|
incidence: self.vertices[start_vertex].first_incidence,
|
||||||
|
}
|
||||||
|
.find(|i| self.incidences[*i].next.is_some_and(|s| s.0 == e.arr_idx()))
|
||||||
|
.expect("cannot find previous incidence, corrupt internal data state");
|
||||||
|
self.incidences[previous].next = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Graph {
|
impl Default for Graph {
|
||||||
@@ -125,8 +167,27 @@ impl GraphTopologyDeletion for Graph {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "e" must index the first of two paired incidences. We want to avoid the calculations required
|
||||||
|
// to allow either of the incidences to be specified, if possible.
|
||||||
|
// The incidence entries are removed before patching the linked lists. This is safe because
|
||||||
|
// delete_incidence() searches by raw slot index (IncidenceSlot.0) and only dereferences the
|
||||||
|
// predecessor node, never the removed entries themselves.
|
||||||
fn delete_edge(&mut self, e: Self::Edge) {
|
fn delete_edge(&mut self, e: Self::Edge) {
|
||||||
todo!()
|
let f = self
|
||||||
|
.incidences
|
||||||
|
.get_idx(e.arr_idx() + 1)
|
||||||
|
.expect("invalid paired incidence index, corrupt internal data state");
|
||||||
|
let e_entry = &self
|
||||||
|
.incidences
|
||||||
|
.remove(e)
|
||||||
|
.expect("attempt to delete an invalid edge");
|
||||||
|
let f_entry = &self
|
||||||
|
.incidences
|
||||||
|
.remove(f)
|
||||||
|
.expect("cannot read paired incidence, corrupt internal data state");
|
||||||
|
|
||||||
|
self.delete_incidence(f, e_entry.neighbor, f_entry.next);
|
||||||
|
self.delete_incidence(e, f_entry.neighbor, e_entry.next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user