SparseList<T>实现了一个稀疏列表数据结构,它具有以下特点:
核心概念
维护一个固定大小的底层数组 (
Vec<Option<T>>)支持高效的索引重用(删除元素后,其索引可以被新插入的元素重用)
通过
free_indices队列管理可用的空闲索引
主要特性
1. 插入操作 (insert)
优先使用空闲索引(如果有的话)
如果没有空闲索引,则追加到数组末尾
返回插入位置的索引
2. 删除操作 (remove)
将指定位置的元素设为
None将该索引加入空闲索引队列
返回被删除的元素
3. 内存管理
不会收缩底层数组:删除元素只是标记为可用,不释放内存
索引重用机制避免内存碎片
clear()会重置所有位置为空,但保持数组容量
使用场景
这种数据结构适用于:
对象池/资源管理:需要频繁创建销毁对象,且希望重用标识符
游戏开发:实体组件系统(ECS)中的实体ID管理
需要稳定索引的场景:索引在对象生命周期内保持不变
use std::collections::VecDeque;
pub struct SparseList<T> {
data: Vec<Option<T>>,
free_indices: VecDeque<usize>,
}
impl<T> SparseList<T> {
pub fn new() -> Self {
SparseList {
data: Vec::new(),
free_indices: VecDeque::new(),
}
}
pub fn insert(&mut self, value: T) -> usize {
if let Some(index) = self.free_indices.pop_front() {
self.data[index] = Some(value);
index
} else {
self.data.push(Some(value));
self.data.len() - 1
}
}
pub fn remove(&mut self, index: usize) -> Option<T> {
if index < self.data.len() {
let ret = self.data[index].take();
self.free_indices.push_back(index);
ret
} else {
panic!("Index out of bounds");
}
}
pub fn clear(&mut self) {
self.data.iter_mut().for_each(|item| *item = None);
self.free_indices.clear();
self.free_indices.extend(0..self.data.len());
}
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.data.len() {
self.data[index].as_ref()
} else {
None
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.data.len() {
self.data[index].as_mut()
} else {
None
}
}
pub fn len(&self) -> usize {
self.data.len()
}
}