#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SparseSet<T> {
sparse: Vec<usize>,
dense: Vec<T>,
}
impl<T> SparseSet<T> {
pub const NULL_INDEX: usize = usize::MAX;
pub fn new() -> Self {
Self {
sparse: Vec::new(),
dense: Vec::new(),
}
}
pub fn insert(&mut self, value: T) -> usize {
let index = self.sparse.len();
if index == Self::NULL_INDEX {
return Self::NULL_INDEX;
}
self.sparse.insert(index, self.dense.len());
self.dense.push(value);
index
}
pub fn get(&self, index: usize) -> Option<&T> {
if index == Self::NULL_INDEX {
None
} else if let Some(i) = self.sparse.get(index).copied() {
self.dense.get(i)
} else {
None
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index == Self::NULL_INDEX {
None
} else if let Some(i) = self.sparse.get(index).copied() {
self.dense.get_mut(i)
} else {
None
}
}
pub fn remove(&mut self, index: usize) -> Option<T> {
if index == Self::NULL_INDEX {
return None;
}
if self.dense.is_empty() {
return None;
}
let dense_index = self.sparse.get(index).copied()?;
let back = self.dense.len() - 1;
self.dense.swap(dense_index, back);
let value = self.dense.remove(back);
self.sparse[index] = Self::NULL_INDEX;
self.sparse[back] = index;
Some(value)
}
pub fn len(&self) -> usize {
self.dense.len()
}
pub fn capacity(&self) -> usize {
self.dense.capacity()
}
pub fn is_empty(&self) -> bool {
self.dense.is_empty()
}
pub fn dense(&self) -> &[T] {
&self.dense
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.dense.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.dense.iter_mut()
}
}
impl<T> IntoIterator for SparseSet<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.dense.into_iter()
}
}
impl<T> Default for SparseSet<T> {
fn default() -> Self {
Self {
sparse: Vec::new(),
dense: Vec::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn insert_remove_get() {
let mut set = SparseSet::new();
set.insert(1);
let i = set.insert(2);
let j = set.insert(3);
set.remove(i);
println!("{}", set.get(j).unwrap());
}
}