pub mod max;
pub mod stable;
pub mod stable_max;
use std::{
collections::{BinaryHeap, HashSet},
hash::Hash,
};
use crate::iter::SortedHeapIter;
pub struct UniquePrioContainer<T> {
container: BinaryHeap<T>,
hash: HashSet<T>,
total_pushed: usize,
capacity: usize,
}
impl<T: Ord + Clone + Hash> UniquePrioContainer<T> {
#[inline]
pub fn new(capacity: usize) -> Self {
let container = BinaryHeap::new();
let hash = HashSet::new();
Self {
container,
hash,
total_pushed: 0,
capacity,
}
}
#[inline]
pub fn new_allocated(capacity: usize) -> Self {
let container = BinaryHeap::with_capacity(capacity);
let hash = HashSet::with_capacity(capacity);
Self {
container,
hash,
total_pushed: 0,
capacity,
}
}
pub fn insert(&mut self, item: T) -> bool {
if self.hash.contains(&item) {
self.replace_eq(item);
return false;
}
self.hash.insert(item.clone());
if self.container.len() < self.capacity {
self.container.push(item);
self.total_pushed += 1;
return true;
}
let min_item = unsafe { self.container.peek().unwrap_unchecked() };
if *min_item <= item {
self.total_pushed += 1;
return false;
}
*unsafe { self.container.peek_mut().unwrap_unchecked() } = item;
self.total_pushed += 1;
true
}
#[inline]
pub fn contains(&self, item: &T) -> bool {
self.container.iter().any(|i| *i == *item)
}
fn replace_eq(&mut self, item: T) {
let need_replace = self.container.iter().any(|i| *i == item && item < *i);
if need_replace {
let add: Vec<_> = self.container.drain().filter(|i| *i != item).collect();
self.container.extend(add);
self.container.push(item);
}
}
}
impl<T> UniquePrioContainer<T> {
#[inline]
pub fn len(&self) -> usize {
self.container.len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.container.capacity()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.container.is_empty()
}
#[inline]
pub fn total_pushed(&self) -> usize {
self.total_pushed
}
}
impl<T: Ord + Clone + Hash> Extend<T> for UniquePrioContainer<T> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for i in iter.into_iter() {
self.insert(i);
}
}
}
impl<T: Ord> IntoIterator for UniquePrioContainer<T> {
type Item = T;
type IntoIter = SortedHeapIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
SortedHeapIter::new(self.container)
}
}