use std::fmt;
use std::iter;
use std::mem::replace;
use std::ops::{Index, IndexMut};
use std::slice;
use {
EdgeType,
Directed,
Outgoing,
EdgeDirection,
};
use super::{
DefIndex,
Edge,
EdgeIndex,
Graph,
index_twice,
IndexType,
Node,
NodeIndex,
node_index,
DIRECTIONS,
Pair,
};
pub struct StableGraph<N, E, Ty = Directed, Ix = DefIndex>
where Ix: IndexType
{
g: Graph<Option<N>, Option<E>, Ty, Ix>,
node_count: usize,
edge_count: usize,
free_node: NodeIndex<Ix>,
free_edge: EdgeIndex<Ix>,
}
impl<N, E, Ty, Ix> fmt::Debug for StableGraph<N, E, Ty, Ix> where
N: fmt::Debug, E: fmt::Debug, Ty: EdgeType, Ix: IndexType
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "{:?}", self.g));
try!(writeln!(f, "free_node={:?}", self.free_node));
try!(writeln!(f, "free_edge={:?}", self.free_edge));
try!(writeln!(f, "node_count={:?}", self.node_count));
try!(writeln!(f, "edge_count={:?}", self.edge_count));
Ok(())
}
}
impl<N, E> StableGraph<N, E, Directed> {
pub fn new() -> Self {
Self::with_capacity(0, 0)
}
}
impl<N, E, Ty, Ix> StableGraph<N, E, Ty, Ix>
where Ty: EdgeType,
Ix: IndexType,
{
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
StableGraph {
g: Graph::with_capacity(nodes, edges),
node_count: 0,
edge_count: 0,
free_node: NodeIndex::end(),
free_edge: EdgeIndex::end(),
}
}
pub fn capacity(&self) -> (usize, usize) {
self.g.capacity()
}
pub fn clear(&mut self) {
self.node_count = 0;
self.edge_count = 0;
self.free_node = NodeIndex::end();
self.free_edge = EdgeIndex::end();
self.g.clear();
}
pub fn node_count(&self) -> usize {
self.node_count
}
pub fn edge_count(&self) -> usize {
self.edge_count
}
#[inline]
pub fn is_directed(&self) -> bool {
Ty::is_directed()
}
pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
let index = if self.free_node != NodeIndex::end() {
let node_idx = self.free_node;
let node_slot = &mut self.g.nodes[node_idx.index()];
let _old = replace(&mut node_slot.weight, Some(weight));
debug_assert!(_old.is_none());
self.free_node = node_slot.next[0]._into_node();
node_slot.next[0] = EdgeIndex::end();
node_idx
} else {
self.g.add_node(Some(weight))
};
self.node_count += 1;
index
}
pub fn remove_node(&mut self, a: NodeIndex<Ix>) -> Option<N> {
let node_weight = match self.g.nodes.get_mut(a.index()) {
None => return None,
Some(n) => n.weight.take(),
};
if let None = node_weight {
return None;
}
for d in DIRECTIONS.iter() {
let k = *d as usize;
loop {
let next = self.g.nodes[a.index()].next[k];
if next == EdgeIndex::end() {
break
}
let ret = self.remove_edge(next);
debug_assert!(ret.is_some());
let _ = ret;
}
}
let node_slot = &mut self.g.nodes[a.index()];
node_slot.next = [self.free_node._into_edge(), EdgeIndex::end()];
self.free_node = a;
self.node_count -= 1;
node_weight
}
pub fn contains_node(&self, a: NodeIndex<Ix>) -> bool {
self.g.nodes.get(a.index()).map_or(false, |no| no.weight.is_some())
}
pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E)
-> EdgeIndex<Ix>
{
if self.free_edge != EdgeIndex::end() {
let edge_idx = self.free_edge;
let edge = &mut self.g.edges[edge_idx.index()];
let _old = replace(&mut edge.weight, Some(weight));
debug_assert!(_old.is_none());
self.free_edge = edge.next[0];
edge.node = [a, b];
match index_twice(&mut self.g.nodes, a.index(), b.index()) {
Pair::None => panic!("StableGraph::add_edge: node indices out of bounds"),
Pair::One(an) => {
edge.next = an.next;
an.next[0] = edge_idx;
an.next[1] = edge_idx;
}
Pair::Both(an, bn) => {
edge.next = [an.next[0], bn.next[1]];
an.next[0] = edge_idx;
bn.next[1] = edge_idx;
}
}
self.edge_count += 1;
edge_idx
} else {
self.edge_count += 1;
self.g.add_edge(a, b, Some(weight))
}
}
pub fn remove_edge(&mut self, e: EdgeIndex<Ix>) -> Option<E> {
let (is_edge, edge_node, edge_next) = match self.g.edges.get(e.index()) {
None => return None,
Some(x) => (x.weight.is_some(), x.node, x.next),
};
if !is_edge {
return None;
}
self.g.change_edge_links(edge_node, e, edge_next);
let edge = &mut self.g.edges[e.index()];
edge.next = [self.free_edge, EdgeIndex::end()];
edge.node = [NodeIndex::end(), NodeIndex::end()];
self.free_edge = e;
self.edge_count -= 1;
edge.weight.take()
}
pub fn node_weight(&self, a: NodeIndex<Ix>) -> Option<&N> {
match self.g.nodes.get(a.index()) {
Some(no) => no.weight.as_ref(),
None => None,
}
}
pub fn node_weight_mut(&mut self, a: NodeIndex<Ix>) -> Option<&mut N> {
match self.g.nodes.get_mut(a.index()) {
Some(no) => no.weight.as_mut(),
None => None,
}
}
pub fn node_indices(&self) -> NodeIndices<N, Ix> {
NodeIndices {
iter: self.g.nodes.iter().enumerate(),
}
}
pub fn edge_weight(&self, e: EdgeIndex<Ix>) -> Option<&E> {
match self.g.edges.get(e.index()) {
Some(ed) => ed.weight.as_ref(),
None => None,
}
}
pub fn edge_weight_mut(&mut self, e: EdgeIndex<Ix>) -> Option<&mut E> {
match self.g.edges.get_mut(e.index()) {
Some(ed) => ed.weight.as_mut(),
None => None,
}
}
pub fn edge_endpoints(&self, e: EdgeIndex<Ix>)
-> Option<(NodeIndex<Ix>, NodeIndex<Ix>)>
{
match self.g.edges.get(e.index()) {
Some(ed) if ed.weight.is_some() => Some((ed.source(), ed.target())),
_otherwise => None,
}
}
pub fn find_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>>
{
let index = self.g.find_edge(a, b);
if let Some(i) = index {
debug_assert!(self.g.edges[i.index()].weight.is_some());
}
index
}
pub fn neighbors(&self, a: NodeIndex<Ix>) -> Neighbors<E, Ix> {
self.neighbors_directed(a, Outgoing)
}
pub fn neighbors_directed(&self, a: NodeIndex<Ix>, dir: EdgeDirection)
-> Neighbors<E, Ix>
{
let mut iter = self.neighbors_undirected(a);
if self.is_directed() {
let k = dir as usize;
iter.next[1 - k] = EdgeIndex::end();
iter.skip_start = NodeIndex::end();
}
iter
}
pub fn neighbors_undirected(&self, a: NodeIndex<Ix>) -> Neighbors<E, Ix>
{
Neighbors {
skip_start: a,
edges: &self.g.edges,
next: match self.g.nodes.get(a.index()) {
None => [EdgeIndex::end(), EdgeIndex::end()],
Some(n) => n.next,
}
}
}
}
impl<N, E, Ty, Ix: IndexType> Clone for StableGraph<N, E, Ty, Ix>
where N: Clone, E: Clone,
{
fn clone(&self) -> Self {
StableGraph {
g: self.g.clone(),
node_count: self.node_count,
edge_count: self.edge_count,
free_node: self.free_node,
free_edge: self.free_edge,
}
}
fn clone_from(&mut self, rhs: &Self) {
self.g.clone_from(&rhs.g);
self.node_count = rhs.node_count;
self.edge_count = rhs.edge_count;
self.free_node = rhs.free_node;
self.free_edge = rhs.free_edge;
}
}
impl<N, E, Ty, Ix> Index<NodeIndex<Ix>> for StableGraph<N, E, Ty, Ix> where
Ty: EdgeType,
Ix: IndexType,
{
type Output = N;
fn index(&self, index: NodeIndex<Ix>) -> &N {
self.node_weight(index).unwrap()
}
}
impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for StableGraph<N, E, Ty, Ix> where
Ty: EdgeType,
Ix: IndexType,
{
fn index_mut(&mut self, index: NodeIndex<Ix>) -> &mut N {
self.node_weight_mut(index).unwrap()
}
}
impl<N, E, Ty, Ix> Index<EdgeIndex<Ix>> for StableGraph<N, E, Ty, Ix> where
Ty: EdgeType,
Ix: IndexType,
{
type Output = E;
fn index(&self, index: EdgeIndex<Ix>) -> &E {
self.edge_weight(index).unwrap()
}
}
impl<N, E, Ty, Ix> IndexMut<EdgeIndex<Ix>> for StableGraph<N, E, Ty, Ix> where
Ty: EdgeType,
Ix: IndexType,
{
fn index_mut(&mut self, index: EdgeIndex<Ix>) -> &mut E {
self.edge_weight_mut(index).unwrap()
}
}
impl<N, E, Ty, Ix> Default for StableGraph<N, E, Ty, Ix>
where Ty: EdgeType,
Ix: IndexType,
{
fn default() -> Self { Self::with_capacity(0, 0) }
}
pub struct Neighbors<'a, E: 'a, Ix: 'a = DefIndex> where
Ix: IndexType,
{
skip_start: NodeIndex<Ix>,
edges: &'a [Edge<Option<E>, Ix>],
next: [EdgeIndex<Ix>; 2],
}
impl<'a, E, Ix> Neighbors<'a, E, Ix>
where Ix: IndexType,
{
pub fn detach(&self) -> WalkNeighbors<Ix> {
WalkNeighbors {
inner: super::WalkNeighbors {
skip_start: self.skip_start,
next: self.next
},
}
}
}
impl<'a, E, Ix> Iterator for Neighbors<'a, E, Ix> where
Ix: IndexType,
{
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<NodeIndex<Ix>> {
match self.edges.get(self.next[0].index()) {
None => {}
Some(edge) => {
debug_assert!(edge.weight.is_some());
self.next[0] = edge.next[0];
return Some((edge.node[1]));
}
}
while let Some(edge) = self.edges.get(self.next[1].index()) {
debug_assert!(edge.weight.is_some());
self.next[1] = edge.next[1];
if edge.node[0] != self.skip_start {
return Some((edge.node[0]));
}
}
None
}
}
pub struct WalkNeighbors<Ix> {
inner: super::WalkNeighbors<Ix>,
}
impl<Ix: IndexType> WalkNeighbors<Ix> {
pub fn next<N, E, Ty: EdgeType>(&mut self, g: &StableGraph<N, E, Ty, Ix>)
-> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)> {
self.inner.next(&g.g)
}
pub fn next_node<N, E, Ty: EdgeType>(&mut self, g: &StableGraph<N, E, Ty, Ix>)
-> Option<NodeIndex<Ix>>
{
self.next(g).map(|t| t.1)
}
pub fn next_edge<N, E, Ty: EdgeType>(&mut self, g: &StableGraph<N, E, Ty, Ix>)
-> Option<EdgeIndex<Ix>>
{
self.next(g).map(|t| t.0)
}
}
pub struct NodeIndices<'a, N: 'a, Ix: IndexType = DefIndex> {
iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
}
impl<'a, N, Ix: IndexType> Iterator for NodeIndices<'a, N, Ix> {
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.by_ref().filter_map(|(i, node)| {
if node.weight.is_some() {
Some(node_index(i))
} else { None }
}).next()
}
}
impl<'a, N, Ix: IndexType> DoubleEndedIterator for NodeIndices<'a, N, Ix> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.by_ref().filter_map(|(i, node)| {
if node.weight.is_some() {
Some(node_index(i))
} else { None }
}).next_back()
}
}
#[test]
fn stable_graph() {
let mut gr = StableGraph::<_, _>::with_capacity(0, 0);
let a = gr.add_node(0);
let b = gr.add_node(1);
let c = gr.add_node(2);
let _ed = gr.add_edge(a, b, 1);
println!("{:?}", gr);
gr.remove_node(b);
println!("{:?}", gr);
let d = gr.add_node(3);
println!("{:?}", gr);
gr.remove_node(a);
gr.remove_node(c);
println!("{:?}", gr);
gr.add_edge(d, d, 2);
println!("{:?}", gr);
let e = gr.add_node(4);
gr.add_edge(d, e, 3);
println!("{:?}", gr);
for neigh in gr.neighbors(d) {
println!("edge {:?} -> {:?}", d, neigh);
}
}
#[test]
fn dfs() {
use Dfs;
let mut gr = StableGraph::<_, _>::with_capacity(0, 0);
let a = gr.add_node("a");
let b = gr.add_node("b");
let c = gr.add_node("c");
let d = gr.add_node("d");
gr.add_edge(a, b, 1);
gr.add_edge(a, c, 2);
gr.add_edge(b, c, 3);
gr.add_edge(b, d, 4);
gr.add_edge(c, d, 5);
gr.add_edge(d, b, 6);
gr.add_edge(c, b, 7);
println!("{:?}", gr);
let mut dfs = Dfs::new(&gr, a);
while let Some(next) = dfs.next(&gr) {
println!("dfs visit => {:?}, weight={:?}", next, &gr[next]);
}
}