#[derive(Clone, Debug)]
pub struct HammingHeap<T> {
distances: Vec<Vec<T>>,
best: u32,
}
impl<T> HammingHeap<T> {
pub fn new() -> Self {
Self::default()
}
pub fn new_distances(distances: usize) -> Self {
let mut s = Self::new();
s.set_distances(distances);
s
}
pub fn clear(&mut self) {
for v in self.distances[self.best as usize..].iter_mut() {
v.clear();
}
self.best = 0;
}
pub fn set_distances(&mut self, distances: usize) {
self.distances.clear();
self.distances.resize_with(distances, || vec![]);
self.best = 0;
}
#[inline]
pub fn pop(&mut self) -> Option<(u32, T)> {
loop {
if let Some(node) = self.distances[self.best as usize].pop() {
return Some((self.best, node));
} else if self.best == self.distances.len() as u32 - 1 {
return None;
} else {
self.best += 1;
}
}
}
#[inline]
pub fn push(&mut self, distance: u32, node: T) {
if distance < self.best {
self.best = distance;
}
self.distances[distance as usize].push(node);
}
pub fn best(&self) -> Option<u32> {
self.distances[self.best as usize..]
.iter()
.position(|v| !v.is_empty())
.map(|n| n as u32 + self.best)
}
pub fn iter(&self) -> impl Iterator<Item = (u32, &T)> {
self.distances[self.best as usize..]
.iter()
.enumerate()
.flat_map(|(distance, v)| v.iter().map(move |item| (distance as u32, item)))
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (u32, &mut T)> {
self.distances[self.best as usize..]
.iter_mut()
.enumerate()
.flat_map(|(distance, v)| v.iter_mut().map(move |item| (distance as u32, item)))
}
}
impl<T> Default for HammingHeap<T> {
fn default() -> Self {
Self {
distances: vec![],
best: 0,
}
}
}