关联/随机访问容器

associative / random access container

本文关键字:访问 随机 关联      更新时间:2023-10-16

我正在寻找一种数据结构来保存唯一元素的无序集合,这将支持以下操作

  1. 插入/删除集合中任何位置的元素
  2. 查询元素是否存在
  3. 访问随机元素

天真地,1 和 2 建议使用关联容器,例如 unordered_set,但 3 在元素数量上是线性的。使用随机访问容器,例如 vector ,使 3 变得容易,1 可以在 O(1) 中完成,但随后 2 又是 O(N)。

问题是是否有一种已知的方法可以解决这种线性复杂性?

编辑:通过 3 中的随机元素,我的意思是:给定 N 个元素的任意顺序,检索元素编号j其中j介于 0 和 N-1 之间。对于std::vector来说,它只是下标,对于std::liststd::set,它从begin()开始递增列表/设置迭代器 j 次等。

两个

最适合您的任务的标准容器是 - 就像你说的,vector 1. 和 2. 在 O(n) 和 3. 在 O(1) 中,set 在 1. 和 2. 在 O(log n) 和 3. 在 O(n) 中。根据数据结构的大小,算法复杂性并不那么重要。vector具有数据局部性的额外优势,因此可以更好地利用 CPU 缓存。

如果元素的实际顺序无关紧要,则可以在摊销的 O(1) (push_back) 中插入vector,如果您swap要删除的元素与最后一个元素一起删除该元素,则可以在摊销 O(1) 中进行删除。

如果你真的有一个大数据结构,你可以使用Boost.Multi-Index来构建一个数据结构,其中1.是O(n),2.是O(log n),3.是O(1)。但是,就像我说的,如果你的数据结构不是很大,vector应该就可以了。

如果随机存取索引中的顺序无关紧要,则可以在摊销的 O(log n) (push_back 中插入。对于删除,您不能使用swap技巧,因为这会使其他索引无效。

我一直在寻找这样的数据结构很长时间。

最近,我发现了非常有前途的库,它具有您正在寻找的所有功能。

参见 cntree::set with random access in O(log n)。

这是链接。http://dl.dropbox.com/u/8437476/works/countertree/index.html

虽然它似乎正在开发中,但我认为它非常有用。

根据您对 #3 的需求,std::unordered_set可能非常合适。

我正在寻找具有上述属性的容器,以便我可以迭代所有类似于for(int i = 0; i < myset.size(); ++i) process(myset[i]);的元素。我找到了这个页面,它描述了std::unordered_set::bucket_count()std::unordered_set::begin(size_t bucket_number)std::unordered_set::end(size_t bucket_number)

如果您有 OpenMP 循环,这将变得非常方便,因此您可以编写:

std::unordered_set<Element> myset;
#pragma omp parallel for
for(int i = 0; i < myset.bucket_count(); ++i) {
   for(auto it = myset.begin(i); it != myset.end(i); ++it)
      processElement(*it);
}

这仍然不允许您直接访问myset[i],但它非常接近,因为您可以访问编号存储桶中的元素。

std::unordered_set . 如果使用索引j作为键,则访问元素不是 O(N),它是 O(1)。

如果您有一个要用于查找的唯一索引并且您不关心其他排序,那么您还计划使用什么作为关联容器的键?