Initial release #1
+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 {
|
||||
// TODO: Arena index and generation types could be externalized to Graph.
|
||||
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
||||
@@ -82,6 +95,22 @@ impl Graph {
|
||||
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
|
||||
// incidences arena. "next" is the next incidence after "e" in the source vertex 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).
|
||||
impl GraphTopologyDeletion for Graph {
|
||||
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
|
||||
// update_incidence_list() searches by raw slot index (IncidenceSlot.0) and only dereferences
|
||||
// the predecessor, never the removed entries themselves.
|
||||
fn delete_edge(&mut self, e: Self::Edge) {
|
||||
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");
|
||||
|
||||
let (f, e_entry, f_entry) = self.remove_incidence_pair(e);
|
||||
if e_entry.neighbor != f_entry.neighbor {
|
||||
self.update_incidence_list(e, f_entry.neighbor, e_entry.next, false);
|
||||
self.update_incidence_list(f, e_entry.neighbor, f_entry.next, false);
|
||||
|
||||
Reference in New Issue
Block a user