Files
grapherity/src/models/append_graph.rs
T

127 lines
3.0 KiB
Rust

use crate::traits::GraphTopology;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Vertex(usize);
impl From<Vertex> for usize {
fn from(v: Vertex) -> usize {
v.0
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Incidence(usize);
struct VertexIncidenceHeader {
incidence_count: usize,
first_incidence: Option<Incidence>,
}
struct IncidenceEntry {
next: Option<Incidence>,
neighbor: Vertex,
}
struct VertexNeighborIterator<'a> {
graph: &'a AppendGraph,
incidence: Option<Incidence>,
}
impl<'a> Iterator for VertexNeighborIterator<'a> {
type Item = Vertex;
fn next(&mut self) -> Option<Self::Item> {
let incidence = self.incidence?;
let entry = &self.graph.incidences[incidence.0];
self.incidence = entry.next;
Some(entry.neighbor)
}
}
pub struct AppendGraph {
// TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'?
vertices: Vec<VertexIncidenceHeader>,
incidences: Vec<IncidenceEntry>,
}
impl AppendGraph {
pub fn new() -> Self {
Self {
vertices: vec![],
incidences: vec![],
}
}
// Adds a single incidence of an edge, which is composed by two such incidences, to the
// incidences vector.
fn add_incidence(&mut self, v1: Vertex, v2: Vertex) {
self.incidences.push(IncidenceEntry {
next: self.vertices[v1.0].first_incidence.take(),
neighbor: v2,
});
self.vertices[v1.0].incidence_count += 1;
self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1));
}
}
impl Default for AppendGraph {
fn default() -> Self {
Self::new()
}
}
impl GraphTopology for AppendGraph {
type Vertex = Vertex;
type Edge = Incidence;
fn vertex_count(&self) -> usize {
self.vertices.len()
}
fn edge_count(&self) -> usize {
self.incidences.len() / 2
}
fn degree(&self, v: Self::Vertex) -> usize {
self.vertices[v.0].incidence_count
}
fn are_adjacent(&self, v1: Self::Vertex, v2: Self::Vertex) -> bool {
self.neighbors(v1).any(|x| x == v2)
}
fn vertices(&self) -> impl Iterator<Item = Self::Vertex> {
(0..self.vertices.len()).map(Vertex)
}
fn neighbors(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex> {
VertexNeighborIterator {
graph: self,
incidence: self.vertices[v.0].first_incidence,
}
}
fn add_vertex(&mut self) -> Self::Vertex {
self.vertices.push(VertexIncidenceHeader {
incidence_count: 0,
first_incidence: None,
});
Vertex(self.vertices.len() - 1)
}
fn add_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge {
self.add_incidence(v1, v2);
self.add_incidence(v2, v1);
Incidence(self.incidences.len() - 2)
}
}
#[cfg(test)]
mod tests {
use super::*;
crate::graph_topology_test_fixtures!(AppendGraph);
crate::graph_topology_tests!(AppendGraph);
}