Add documentation for models::append_graph module
This commit is contained in:
@@ -1,13 +1,24 @@
|
|||||||
use crate::maps::{EdgeMap, VertexMap};
|
use crate::maps::{EdgeMap, VertexMap};
|
||||||
use crate::traits::{GraphTopology, IncidenceCursor};
|
use crate::traits::{GraphTopology, IncidenceCursor};
|
||||||
|
|
||||||
|
/// An opaque handle identifying a vertex in an [`AppendGraph`].
|
||||||
|
///
|
||||||
|
/// Handles are stable for the lifetime of the graph. They can be obtained via graph methods like
|
||||||
|
/// [`GraphTopology::add_vertex`] and [`GraphTopology::vertices`].
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Vertex(usize);
|
pub struct Vertex(usize);
|
||||||
|
|
||||||
|
/// An opaque handle identifying an edge in an [`AppendGraph`].
|
||||||
|
///
|
||||||
|
/// Handles are stable for the lifetime of the graph. They can be obtained via graph methods like
|
||||||
|
/// [`GraphTopology::add_edge`] and [`GraphTopology::edges`].
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Edge(usize);
|
pub struct Edge(usize);
|
||||||
|
|
||||||
|
/// A [`VertexMap`] for [`AppendGraph`] vertices.
|
||||||
pub type AppendGraphVertexMap<T> = VertexMap<Vertex, T>;
|
pub type AppendGraphVertexMap<T> = VertexMap<Vertex, T>;
|
||||||
|
|
||||||
|
/// An [`EdgeMap`] for [`AppendGraph`] edges.
|
||||||
pub type AppendGraphEdgeMap<T> = EdgeMap<Edge, T>;
|
pub type AppendGraphEdgeMap<T> = EdgeMap<Edge, T>;
|
||||||
|
|
||||||
impl Edge {
|
impl Edge {
|
||||||
@@ -16,6 +27,7 @@ impl Edge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Check if VertexIncidenceHeader and IncidenceEntry can be made smaller. Currently they both take 24 bytes (on 64bit), see https://stackoverflow.com/a/79653173
|
||||||
struct VertexIncidenceHeader {
|
struct VertexIncidenceHeader {
|
||||||
incidence_count: usize,
|
incidence_count: usize,
|
||||||
first_incidence: Option<Edge>,
|
first_incidence: Option<Edge>,
|
||||||
@@ -27,6 +39,10 @@ struct IncidenceEntry {
|
|||||||
adjacent: Vertex,
|
adjacent: Vertex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A resumable cursor over the incidences of a single vertex in an [`AppendGraph`].
|
||||||
|
///
|
||||||
|
/// Can be obtained via [`GraphTopology::incidence_cursor`]. See [`IncidenceCursor`] on how to use
|
||||||
|
/// it.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct AppendGraphIncidenceCursor {
|
pub struct AppendGraphIncidenceCursor {
|
||||||
incidence: Option<Edge>,
|
incidence: Option<Edge>,
|
||||||
@@ -38,12 +54,45 @@ impl IncidenceCursor<AppendGraph> for AppendGraphIncidenceCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An undirected graph that supports adding vertices and edges, but not deleting them.
|
||||||
|
///
|
||||||
|
/// `AppendGraph` is optimised for workloads that incrementally build a graph and query it
|
||||||
|
/// repeatedly. [`Vertex`]
|
||||||
|
/// and [`Edge`] handles are never invalidated. Use [`Graph`] instead if you need to remove vertices
|
||||||
|
/// or edges.
|
||||||
|
///
|
||||||
|
/// Incidences are stored as interlaced adjacency lists in a single flat [`Vec`]. This means that
|
||||||
|
/// vertex neighborhood traversals in general result in scattered index jumps.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use grapherity::prelude::*;
|
||||||
|
/// use grapherity::models::AppendGraph;
|
||||||
|
///
|
||||||
|
/// let mut graph = AppendGraph::new();
|
||||||
|
/// let v1 = graph.add_vertex();
|
||||||
|
/// let v2 = graph.add_vertex();
|
||||||
|
/// let e = graph.add_edge(v1, v2);
|
||||||
|
/// assert!(graph.are_adjacent(v1, v2));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Time and space complexity
|
||||||
|
///
|
||||||
|
/// Both [`add_vertex`] and [`add_edge`] run in amortised *O(1)* time. [`degree`] runs in *O(1)*
|
||||||
|
/// time since vertex degrees are stored. Space complexity is *O(|V| + |E|)*.
|
||||||
|
///
|
||||||
|
/// [`add_vertex`]: Self::add_vertex
|
||||||
|
/// [`add_edge`]: Self::add_edge
|
||||||
|
/// [`degree`]: Self::degree
|
||||||
|
/// [`Graph`]: crate::models::Graph
|
||||||
pub struct AppendGraph {
|
pub struct AppendGraph {
|
||||||
vertices: Vec<VertexIncidenceHeader>,
|
vertices: Vec<VertexIncidenceHeader>,
|
||||||
incidences: Vec<IncidenceEntry>,
|
incidences: Vec<IncidenceEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppendGraph {
|
impl AppendGraph {
|
||||||
|
/// Creates an empty graph instance with no vertices or edges.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
vertices: vec![],
|
vertices: vec![],
|
||||||
@@ -51,8 +100,8 @@ impl AppendGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a single incidence of an edge, which is composed by two such incidences, to the
|
/// Adds a single incidence of an edge, which is composed by two such incidences, to the
|
||||||
// incidences vector.
|
/// incidences vector.
|
||||||
fn add_incidence(&mut self, v1: Vertex, v2: Vertex) {
|
fn add_incidence(&mut self, v1: Vertex, v2: Vertex) {
|
||||||
self.incidences.push(IncidenceEntry {
|
self.incidences.push(IncidenceEntry {
|
||||||
next: self.vertices[v1.0].first_incidence.take(),
|
next: self.vertices[v1.0].first_incidence.take(),
|
||||||
|
|||||||
Reference in New Issue
Block a user