use std::rc::Rc;
use std::ops::Deref;
use std::cmp::Ordering;
#[derive(Debug, PartialEq, Eq)]
pub enum OrdMap<K, V> {
Tree(OrdMapColor, K, V, Rc<OrdMap<K, V>>, Rc<OrdMap<K, V>>),
Nil
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrdMapColor {
Red,
Black
}
impl<K, V> Clone for OrdMap<K, V>
where K: Clone,
V: Clone
{
fn clone(&self) -> Self {
match self {
&OrdMap::Tree(color, ref key, ref val, ref left, ref right) => {
OrdMap::Tree(color, key.clone(), val.clone(), left.clone(), right.clone())
},
&OrdMap::Nil => {
OrdMap::Nil
}
}
}
}
impl<K, V> OrdMap<K, V>
where K: Clone + Eq + Ord,
V: Clone
{
#[inline]
pub fn is_empty(&self) -> bool {
match &self {
&OrdMap::Tree(_, _, _, _, _) => false,
&OrdMap::Nil => true
}
}
pub fn empty() -> Self {
OrdMap::Nil
}
pub fn collect(&self) -> Vec<(K, V)> {
let mut vs = Vec::new();
let mut f = |key: &K, val: &V| {
vs.push((key.clone(), val.clone()));
None
};
let _: Option<isize> = self.find(&mut f);
vs
}
pub fn contains_key(&self, key: &K) -> bool {
self.get(key).is_some()
}
pub fn get(&self, key: &K) -> Option<&V> {
let mut p = self;
loop {
match p {
&OrdMap::Tree(_, ref key0, ref val0, ref left, ref right) => {
match key.cmp(key0) {
Ordering::Less => {
p = left.deref();
},
Ordering::Greater => {
p = right.deref();
},
Ordering::Equal => {
return Some(val0);
}
}
},
&OrdMap::Nil => {
return None;
}
}
}
}
pub fn first_key_value(&self) -> Option<(&K, &V)> {
let mut p = self;
loop {
match p {
&OrdMap::Tree(_, ref key, ref val, ref left, _) if left.is_empty() => {
return Some((key, val));
},
&OrdMap::Tree(_, _, _, ref left, _) => {
p = left.deref();
}
&OrdMap::Nil => {
return None;
}
}
}
}
pub fn last_key_value(&self) -> Option<(&K, &V)> {
let mut p = self;
loop {
match p {
&OrdMap::Tree(_, ref key, ref val, _, ref right) if right.is_empty() => {
return Some((key, val));
},
&OrdMap::Tree(_, _, _, _, ref right) => {
p = right.deref();
}
&OrdMap::Nil => {
return None;
}
}
}
}
pub fn find<F, T>(&self, pred: &mut F) -> Option<T>
where F: FnMut(&K, &V) -> Option<T>
{
match self {
&OrdMap::Tree(_, ref key, ref val, ref left, ref right) => {
match left.find(pred) {
z @ Some(_) => z,
None => {
match pred(key, val) {
z @ Some(_) => z,
None => right.find(pred)
}
}
}
},
&OrdMap::Nil => {
None
}
}
}
pub fn insert(&self, key: K, val: V) -> OrdMap<K, V> {
self.ins(key, val).make_black()
}
fn ins(&self, key: K, val: V) -> OrdMap<K, V> {
match self {
&OrdMap::Tree(color0, ref key0, ref val0, ref left, ref right) => {
match key.cmp(key0) {
Ordering::Less => {
Self::balance(color0, key0, val0, &Rc::new(left.ins(key, val)), right)
},
Ordering::Greater => {
Self::balance(color0, key0, val0, left, &Rc::new(right.ins(key, val)))
},
Ordering::Equal => {
OrdMap::Tree(color0, key, val, left.clone(), right.clone())
}
}
},
&OrdMap::Nil => {
OrdMap::Tree(OrdMapColor::Red, key, val, Rc::new(OrdMap::Nil), Rc::new(OrdMap::Nil))
}
}
}
fn make_black(&self) -> OrdMap<K, V> {
match self {
&OrdMap::Tree(_, ref key, ref val, ref left, ref right) => {
OrdMap::Tree(OrdMapColor::Black, key.clone(), val.clone(), left.clone(), right.clone())
},
&OrdMap::Nil => {
OrdMap::Nil
}
}
}
fn balance(color: OrdMapColor, key: &K, val: &V, left: &Rc<OrdMap<K, V>>, right: &Rc<OrdMap<K, V>>) -> OrdMap<K, V> {
if color == OrdMapColor::Black {
match left.deref() {
&OrdMap::Tree(OrdMapColor::Red, ref key2, ref val2, ref left2, ref right2) => {
match left2.deref() {
&OrdMap::Tree(OrdMapColor::Red, ref key3, ref val3, ref left3, ref right3) => {
return OrdMap::Tree(OrdMapColor::Red, key2.clone(), val2.clone(),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key3.clone(), val3.clone(), left3.clone(), right3.clone())),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key.clone(), val.clone(), right2.clone(), right.clone())))
},
_ => {}
};
match right2.deref() {
&OrdMap::Tree(OrdMapColor::Red, ref key3, ref val3, ref left3, ref right3) => {
return OrdMap::Tree(OrdMapColor::Red, key3.clone(), val3.clone(),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key2.clone(), val2.clone(), left2.clone(), left3.clone())),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key.clone(), val.clone(), right3.clone(), right.clone())))
},
_ => {}
};
},
_ => {}
}
match right.deref() {
&OrdMap::Tree(OrdMapColor::Red, ref key2, ref val2, ref left2, ref right2) => {
match left2.deref() {
&OrdMap::Tree(OrdMapColor::Red, ref key3, ref val3, ref left3, ref right3) => {
return OrdMap::Tree(OrdMapColor::Red, key3.clone(), val3.clone(),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key.clone(), val.clone(), left.clone(), left3.clone())),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key2.clone(), val2.clone(), right3.clone(), right2.clone())))
},
_ => {}
};
match right2.deref() {
&OrdMap::Tree(OrdMapColor::Red, ref key3, ref val3, ref left3, ref right3) => {
return OrdMap::Tree(OrdMapColor::Red, key2.clone(), val2.clone(),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key.clone(), val.clone(), left.clone(), left2.clone())),
Rc::new(OrdMap::Tree(OrdMapColor::Black, key3.clone(), val3.clone(), left3.clone(), right3.clone())))
},
_ => {}
};
},
_ => {}
}
}
OrdMap::Tree(color, key.clone(), val.clone(), left.clone(), right.clone())
}
pub fn depth(&self) -> usize {
match self {
&OrdMap::Tree(_, _, _, ref left, ref right) => {
1 + left.depth().max(right.depth())
},
&OrdMap::Nil => {
0
}
}
}
pub fn size(&self) -> usize {
match self {
&OrdMap::Tree(_, _, _, ref left, ref right) => {
1 + left.size() + right.size()
},
&OrdMap::Nil => {
0
}
}
}
}