Add Graph::delete_vertex() implementation
This commit is contained in:
+47
-14
@@ -56,6 +56,19 @@ impl<'a> Iterator for VertexIncidenceIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VertexIncidenceCursor {
|
||||||
|
incidence: Option<IncidenceSlot>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VertexIncidenceCursor {
|
||||||
|
fn next(&mut self, graph: &Graph) -> Option<Edge> {
|
||||||
|
let current = self.incidence?;
|
||||||
|
let index = graph.incidences.get_idx(current.0)?;
|
||||||
|
self.incidence = 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>,
|
||||||
@@ -82,6 +95,22 @@ impl Graph {
|
|||||||
edge
|
edge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_incidence_pair(&mut self, e: Edge) -> (Edge, IncidenceEntry, IncidenceEntry) {
|
||||||
|
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");
|
||||||
|
(f, e_entry, f_entry)
|
||||||
|
}
|
||||||
|
|
||||||
// Updates the source vertex incidence list after the incidence "e" was deleted from the
|
// Updates the source vertex incidence list after the incidence "e" was deleted from the
|
||||||
// incidences arena. "next" is the next incidence after "e" in the source vertex incidence list.
|
// incidences arena. "next" is the next incidence after "e" in the source vertex incidence list.
|
||||||
fn update_incidence_list(
|
fn update_incidence_list(
|
||||||
@@ -169,26 +198,30 @@ impl GraphTopology for Graph {
|
|||||||
// TODO: Benchmark delete with storing "previous" in O(1) vs. linear lookup in O(degree).
|
// TODO: Benchmark delete with storing "previous" in O(1) vs. linear lookup in O(degree).
|
||||||
impl GraphTopologyDeletion for Graph {
|
impl GraphTopologyDeletion for Graph {
|
||||||
fn delete_vertex(&mut self, v: Self::Vertex) {
|
fn delete_vertex(&mut self, v: Self::Vertex) {
|
||||||
todo!()
|
let v_header = self
|
||||||
|
.vertices
|
||||||
|
.remove(v)
|
||||||
|
.expect("attempt to delete an invalid vertex");
|
||||||
|
let mut cursor = VertexIncidenceCursor {
|
||||||
|
incidence: v_header.first_incidence,
|
||||||
|
};
|
||||||
|
while let Some(e) = cursor.next(self) {
|
||||||
|
// Since v is being deleted, there are no update_incidence_list() calls for e, no need
|
||||||
|
// to fix v's incidence list.
|
||||||
|
let (f, e_entry, f_entry) = self.remove_incidence_pair(e);
|
||||||
|
if e_entry.neighbor != f_entry.neighbor {
|
||||||
|
self.update_incidence_list(f, e_entry.neighbor, f_entry.next, false);
|
||||||
|
} else {
|
||||||
|
cursor.incidence = f_entry.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The incidence entries are removed before patching the linked lists. This is safe because
|
// The incidence entries are removed before patching the linked lists. This is safe because
|
||||||
// update_incidence_list() searches by raw slot index (IncidenceSlot.0) and only dereferences
|
// update_incidence_list() searches by raw slot index (IncidenceSlot.0) and only dereferences
|
||||||
// the predecessor, never the removed entries themselves.
|
// the predecessor, never the removed entries themselves.
|
||||||
fn delete_edge(&mut self, e: Self::Edge) {
|
fn delete_edge(&mut self, e: Self::Edge) {
|
||||||
let f = self
|
let (f, e_entry, f_entry) = self.remove_incidence_pair(e);
|
||||||
.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");
|
|
||||||
|
|
||||||
if e_entry.neighbor != f_entry.neighbor {
|
if e_entry.neighbor != f_entry.neighbor {
|
||||||
self.update_incidence_list(e, f_entry.neighbor, e_entry.next, false);
|
self.update_incidence_list(e, f_entry.neighbor, e_entry.next, false);
|
||||||
self.update_incidence_list(f, e_entry.neighbor, f_entry.next, false);
|
self.update_incidence_list(f, e_entry.neighbor, f_entry.next, false);
|
||||||
|
|||||||
Reference in New Issue
Block a user