我正在寻找一个数据结构来保存无序的独特元素集合,这将支持以下操作
天真地,1和2建议使用关联容器,例如, unordered_set
,但是3是元素数量的线性。使用随机访问容器,例如vector
,使3变容易,1可以在O(1)中完成,但是2又是O(N)。
问题是这种线性复杂性是否已知?
编辑:通过3中的随机元素,我的意思是:给定N个元素的任意排序,检索元素编号j
,其中j
介于0和N-1之间。对于std::vector
它只是下标,对于std::list
或std::set
,它从begin()
等开始递增列表/设置迭代器j次。
答案 0 :(得分:3)
最适合您任务的两个标准容器 - 就像你说的那样,vector
有1.和2.在O(n)和3.在O(1)和{{1}使用1.和2.在O(log n)中和3.在O(n)中。根据数据结构的大小,算法的复杂性并不重要。 set
具有数据局部性的额外优势,因此可以更好地利用CPU Cache。
如果元素的实际顺序无关紧要,可以在摊销的O(1)(vector
)中插入vector
,并且可以在摊销的O(1)中完成删除如果您push_back
要删除最后一个元素的元素并将其删除。
如果你真的有一个大数据结构,可以使用Boost.Multi-Index来构建一个数据结构,其中1.是O(n),2是O(log n),3是O(1) 。但是,正如我所说,如果您的数据结构不是很大,swap
应该可以正常工作。
如果随机访问索引中的顺序无关紧要,可以在分摊的O(log n)(vector
)中完成插入。对于删除,您不能使用push_back
技巧,因为这会使其他索引无效。
答案 1 :(得分:1)
我一直在寻找这样的数据结构。
最近,我发现了一个非常有前途的库,它具有您正在寻找的所有功能。
在O(log n)中查看带有随机访问的cntree :: set。
这是链接。 http://dl.dropbox.com/u/8437476/works/countertree/index.html
虽然它似乎正在开发中,但我发现它非常实用。
答案 2 :(得分:1)
具体取决于您对#3 std::unordered_set
的需求可能非常合适。
我正在寻找具有上述属性的容器,以便我可以迭代所有类似于for(int i = 0; i < myset.size(); ++i) process(myset[i]);
的元素。
我发现this page描述了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]
,但它非常接近,因为您可以访问编号存储桶中的元素。
答案 3 :(得分:0)
std::unordered_set
。如果使用索引j
作为键,则访问元素不是O(N),它是O(1)。
如果您有一个您想要用于查找的唯一索引并且您不关心其他订购,那么您还计划将哪些用作关联容器的键?