use splay_tree::SplayMap;
#[derive(Debug)]
pub struct HeapMap<K, V> {
inner: SplayMap<K, V>,
}
impl<K, V> HeapMap<K, V>
where
K: Ord,
{
pub fn new() -> Self {
HeapMap {
inner: SplayMap::new(),
}
}
pub fn push_if_absent(&mut self, key: K, value: V) -> bool {
if !self.inner.contains_key(&key) {
self.inner.insert(key, value);
true
} else {
false
}
}
pub fn pop_if<F>(&mut self, f: F) -> Option<(K, V)>
where
F: FnOnce(&K, &V) -> bool,
{
if self.inner.smallest().map_or(false, |(k, v)| f(k, v)) {
self.inner.take_smallest()
} else {
None
}
}
pub fn peek(&mut self) -> Option<(&K, &V)> {
self.inner.smallest()
}
pub fn remove(&mut self, key: &K) -> bool {
self.inner.remove(key).is_some()
}
}
impl<K, V> HeapMap<K, V> {
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.inner.len()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn it_works() {
let mut heap = HeapMap::new();
assert_eq!(heap.len(), 0);
assert!(heap.push_if_absent(1, "value-a"));
assert!(!heap.push_if_absent(1, "value-b"));
assert_eq!(heap.len(), 1);
assert!(heap.push_if_absent(0, "value-b"));
assert!(heap.push_if_absent(2, "value-c"));
assert_eq!(heap.peek(), Some((&0, &"value-b")));
assert_eq!(heap.len(), 3);
assert!(heap.remove(&1));
assert_eq!(heap.len(), 2);
assert!(!heap.remove(&1));
assert_eq!(heap.len(), 2);
assert_eq!(heap.pop_if(|_, _| false), None);
assert_eq!(heap.pop_if(|key, _| *key == 0), Some((0, "value-b")));
assert_eq!(heap.pop_if(|key, _| *key == 2), Some((2, "value-c")));
assert_eq!(heap.pop_if(|_, _| true), None);
}
}