std :: set <t> :: insert,duplicate elements </t>

时间:2012-05-09 13:17:47

标签: c++ data-structures stl set

std :: set插入成员函数的有效实现是什么?因为数据结构基于std :: less(运算符&lt;需要为元素类型定义)对元素进行排序,所以在概念上很容易检测到重复。

它如何在内部实际运作?它是否使用了红背树数据结构(Josuttis一书中提到的实现细节)?

标准数据结构的实现可能会有所不同......

我有一个问题,我被迫有一个(一般来说)整数集应该是唯一的。集合的长度各不相同,因此我需要动态数据结构(基于我的狭隘知识,这会将内容缩小到列表,设置)。元素不一定需要排序,但可能没有重复。由于候选集总是有很多重复项(集很小,最多64个元素),因此尝试使用insert成员函数将重复项插入std :: set会导致与std :: list和其他算法相比产生大量开销可能不会诉诸于元素排序?

附加:输出集具有27个元素的固定大小。对不起,我忘了这个...这适用于特殊情况的问题。对于其他情况,长度是任​​意的(低于输入集)。

3 个答案:

答案 0 :(得分:3)

如果您要同时创建整个集合,则可以尝试使用std::vector来保存元素,std::sort对其进行排序,并std::unique删除重复项。

答案 1 :(得分:2)

std::set::insert的复杂性为O(log n),或者如果使用“位置”插入并使位置正确,则摊销O(1)(参见例如http://cplusplus.com/reference/stl/set/insert/)。

底层机制依赖于实现。它通常是一棵红黑树,但这不是强制性的。您应该查看您喜欢的实现的源代码,以了解它正在做什么。

对于小型套装,有可能是由于空间局部性,对矢量的简单线性搜索将更便宜。但插入本身将需要复制以下所有元素。确切知道的唯一方法是分析每个选项。

答案 2 :(得分:2)

当你只提前知道64个可能的值时,只需取一个位字段并翻转实际看到的元素的位。这适用于n + O(1)步骤,你不能少于此。

插入大小为std::set的m需要O(log(m))时间和比较,这意味着为此目的使用std::set将花费O(n * log(n))和如果常数大于简单地对输入进行排序(这需要额外的空间)然后丢弃重复项,我不会感到惊讶。

使用std::list执行相同的操作需要花费O(n ^ 2)的平均时间,因为在列表中查找插入位置需要O(n)。

一次将一个元素插入std::vector也需要O(n ^ 2)个平均时间 - 在O(log(m))中找到插入位置是可行的,但是元素需要我移动到腾出空间。如果最终结果中的元素数量远小于输入,则下降到O(n * log(n)),几乎没有空间开销。

如果您有C ++ 11编译器或使用boost,您还可以使用哈希表。我不确定插入特性,但如果结果中的元素数量与输入大小相比较小,则只需要O(n)时间 - 与位字段不同,您不需要先验地知道结果的潜在元素或大小(虽然知道大小有帮助,因为你可以避免重复)。