#[derive(Clone, Debug)]
pub struct SparseSet {
len: usize,
dense: Vec<usize>,
sparse: Vec<usize>,
}
impl Default for SparseSet {
fn default() -> Self {
Self::new(0)
}
}
impl SparseSet {
#[inline]
pub fn new(capacity: usize) -> Self {
Self {
len: 0,
dense: vec![0; capacity],
sparse: vec![0; capacity],
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.dense.len()
}
#[inline]
pub fn insert(&mut self, id: usize) -> bool {
if self.contains(id) {
return false;
}
debug_assert!(
self.len < self.capacity(),
"SparseSet overflow: len={}, capacity={}",
self.len,
self.capacity()
);
self.dense[self.len] = id;
self.sparse[id] = self.len;
self.len += 1;
true
}
#[inline]
pub fn contains(&self, id: usize) -> bool {
let idx = self.sparse[id];
idx < self.len && self.dense[idx] == id
}
#[inline]
pub fn clear(&mut self) {
self.len = 0;
}
}
#[cfg(test)]
impl SparseSet {
fn len(&self) -> usize {
self.len
}
fn is_empty(&self) -> bool {
self.len == 0
}
fn iter(&self) -> impl Iterator<Item = usize> + '_ {
self.dense[..self.len].iter().copied()
}
fn resize(&mut self, new_capacity: usize) {
self.clear();
self.dense.resize(new_capacity, 0);
self.sparse.resize(new_capacity, 0);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sparse_set_basic() {
let mut set = SparseSet::new(10);
assert!(set.is_empty());
assert_eq!(set.len(), 0);
assert_eq!(set.capacity(), 10);
assert!(set.insert(3));
assert!(set.insert(7));
assert!(set.insert(1));
assert_eq!(set.len(), 3);
assert!(set.contains(3));
assert!(set.contains(7));
assert!(set.contains(1));
assert!(!set.contains(0));
assert!(!set.contains(5));
assert!(!set.insert(3));
assert_eq!(set.len(), 3);
}
#[test]
fn test_sparse_set_insertion_order() {
let mut set = SparseSet::new(10);
set.insert(5);
set.insert(2);
set.insert(8);
set.insert(1);
let items: Vec<_> = set.iter().collect();
assert_eq!(items, vec![5, 2, 8, 1]);
}
#[test]
fn test_sparse_set_clear() {
let mut set = SparseSet::new(10);
set.insert(1);
set.insert(2);
set.insert(3);
assert_eq!(set.len(), 3);
set.clear();
assert!(set.is_empty());
assert!(!set.contains(1));
assert!(!set.contains(2));
assert!(!set.contains(3));
set.insert(5);
assert_eq!(set.len(), 1);
assert!(set.contains(5));
}
#[test]
fn test_sparse_set_resize() {
let mut set = SparseSet::new(5);
set.insert(1);
set.insert(2);
set.resize(20);
assert!(set.is_empty()); assert_eq!(set.capacity(), 20);
set.insert(15); assert!(set.contains(15));
}
}