mod adjacent;
mod algo;
use crate::error::Error;
use self::{
adjacent::*,
algo::{bfs::*, dfs::*, order::*, pfs::*},
};
use std::{
cell::RefCell,
fmt::Display,
hash::Hash,
ops::Deref,
rc::{Rc, Weak},
};
enum Transposition {
Outbound,
Inbound,
}
#[derive(Clone)]
pub struct Edge<K, N, E>(pub Node<K, N, E>, pub Node<K, N, E>, pub E)
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone;
impl<K, N, E> Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
pub fn source(&self) -> &Node<K, N, E> {
&self.0
}
pub fn target(&self) -> &Node<K, N, E> {
&self.1
}
pub fn value(&self) -> &E {
&self.2
}
pub fn reverse(&self) -> Edge<K, N, E> {
Edge(self.1.clone(), self.0.clone(), self.2.clone())
}
}
impl<K, N, E> PartialEq for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
fn eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}
impl<K, N, E> Eq for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
}
impl<K, N, E> PartialOrd for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone + PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.2.partial_cmp(&other.2)
}
}
impl<K, N, E> Ord for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone + PartialOrd + Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.2.cmp(&other.2)
}
}
#[derive(Clone)]
pub struct Node<K = usize, N = (), E = ()>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
inner: NodeInner<K, N, E>,
}
type NodeInner<K, N, E> = Rc<(K, N, RefCell<Adjacent<K, N, E>>)>;
impl<K, N, E> Node<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
pub fn new(key: K, value: N) -> Self {
Node {
inner: NodeInner::new((key, value, Adjacent::new())),
}
}
pub fn key(&self) -> &K {
&self.inner.0
}
pub fn value(&self) -> &N {
&self.inner.1
}
pub fn out_degree(&self) -> usize {
self.inner.2.borrow().len_outbound()
}
pub fn in_degree(&self) -> usize {
self.inner.2.borrow().len_inbound()
}
pub fn connect(&self, other: &Self, value: E) {
self.inner
.2
.borrow_mut()
.push_outbound((other.clone(), value.clone()));
other
.inner
.2
.borrow_mut()
.push_inbound((self.clone(), value));
}
pub fn try_connect(&self, other: &Self, value: E) -> Result<(), Error> {
if self.is_connected(other.key()) {
Err(Error::EdgeAlreadyExists)
} else {
self.connect(other, value);
Ok(())
}
}
pub fn disconnect(&self, other: &K) -> Result<E, Error> {
match self.find_outbound(other) {
Some(other) => match self.inner.2.borrow_mut().remove_outbound(other.key()) {
Ok(edge) => {
other.inner.2.borrow_mut().remove_inbound(self.key())?;
Ok(edge)
}
Err(err) => Err(err),
},
None => Err(Error::EdgeNotFound),
}
}
pub fn isolate(&self) {
for Edge(_, v, _) in self.iter_out() {
v.inner.2.borrow_mut().remove_inbound(self.key()).unwrap();
}
for Edge(v, _, _) in self.iter_in() {
v.inner.2.borrow_mut().remove_outbound(self.key()).unwrap();
}
self.inner.2.borrow_mut().clear_outbound();
self.inner.2.borrow_mut().clear_inbound();
}
pub fn is_root(&self) -> bool {
self.inner.2.borrow().len_inbound() == 0
}
pub fn is_leaf(&self) -> bool {
self.inner.2.borrow().len_outbound() == 0
}
pub fn is_orphan(&self) -> bool {
self.is_root() && self.is_leaf()
}
pub fn is_connected(&self, other: &K) -> bool {
self.find_outbound(other).is_some()
}
pub fn find_outbound(&self, other: &K) -> Option<Node<K, N, E>> {
let edge = self.inner.2.borrow();
let edge = edge.find_outbound(other);
edge.map(|edge| edge.0.upgrade().unwrap())
}
pub fn find_inbound(&self, other: &K) -> Option<Node<K, N, E>> {
let edge = self.inner.2.borrow();
let edge = edge.find_inbound(other);
edge.map(|edge| edge.0.upgrade().unwrap())
}
pub fn preorder(&self) -> Order<K, N, E> {
Order::preorder(self)
}
pub fn postorder(&self) -> Order<K, N, E> {
Order::postroder(self)
}
pub fn dfs(&self) -> Dfs<K, N, E> {
Dfs::new(self)
}
pub fn bfs(&self) -> Bfs<K, N, E> {
Bfs::new(self)
}
pub fn pfs(&self) -> Pfs<K, N, E>
where
N: Ord,
{
Pfs::new(self)
}
pub fn iter_out(&self) -> IterOut<K, N, E> {
IterOut {
node: self,
position: 0,
}
}
pub fn iter_in(&self) -> IterIn<K, N, E> {
IterIn {
node: self,
position: 0,
}
}
pub fn sizeof(&self) -> usize {
std::mem::size_of::<Node<K, N, E>>()
+ std::mem::size_of::<K>()
+ std::mem::size_of::<N>()
+ self.inner.2.borrow().sizeof()
+ std::mem::size_of::<Self>()
}
}
impl<K, N, E> Deref for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
type Target = N;
fn deref(&self) -> &Self::Target {
self.value()
}
}
impl<K, N, E> PartialEq for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
fn eq(&self, other: &Self) -> bool {
self.key() == other.key()
}
}
impl<K, N, E> Eq for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
}
impl<K, N, E> PartialOrd for Node<K, N, E>
where
K: Clone + Hash + PartialEq + Display + Eq,
N: Clone + Ord,
E: Clone,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.value().cmp(other.value()))
}
}
impl<K, N, E> Ord for Node<K, N, E>
where
K: Clone + Hash + PartialEq + Display + Eq,
N: Clone + Ord,
E: Clone,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value().cmp(other.value())
}
}
pub struct IterOut<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
node: &'a Node<K, N, E>,
position: usize,
}
impl<'a, K, N, E> Iterator for IterOut<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
type Item = Edge<K, N, E>;
fn next(&mut self) -> Option<Self::Item> {
match self.node.inner.2.borrow().get_outbound(self.position) {
Some(current) => match current.0.upgrade() {
Some(node) => {
self.position += 1;
Some(Edge(self.node.clone(), node, current.1.clone()))
}
None => {
panic!(
"Target node in the adjacency list of `node = {}` has been dropped.",
self.node.key()
);
}
},
None => None,
}
}
}
pub struct IterIn<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
node: &'a Node<K, N, E>,
position: usize,
}
impl<'a, K, N, E> Iterator for IterIn<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
type Item = Edge<K, N, E>;
fn next(&mut self) -> Option<Self::Item> {
match self.node.inner.2.borrow().get_inbound(self.position) {
Some(current) => match current.0.upgrade() {
Some(node) => {
self.position += 1;
Some(Edge(node, self.node.clone(), current.1.clone()))
}
None => {
panic!(
"Target node in the adjacency list of `node = {}` has been dropped.",
self.node.key()
);
}
},
None => None,
}
}
}
impl<'a, K, N, E> IntoIterator for &'a Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
type Item = Edge<K, N, E>;
type IntoIter = IterOut<'a, K, N, E>;
fn into_iter(self) -> Self::IntoIter {
IterOut {
node: self,
position: 0,
}
}
}