标准::设置:<T>:插入,重复元素

std::set<T>::insert, duplicate elements

本文关键字:元素 插入 设置 lt 标准 gt      更新时间:2023-10-16

std::set insert成员函数的有效实现是什么?由于数据结构基于 std::less(需要为元素类型定义运算符<(对元素进行排序,因此从概念上讲,检测重复项很容易。

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

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

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

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

如果要一次创建整个集合,则可以尝试使用 std::vector 来保存元素,std::sort对它们进行排序,std::unique修剪掉重复项。

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

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

对于小集合,例如,由于空间局部性,对向量的简单线性搜索可能会更便宜。 但是插入本身将需要复制以下所有元素。 确定的唯一方法是分析每个选项。

当你只有 64 个可能的值提前知道时,只需选择一个位字段并翻转实际看到的元素的位。这在 n+O(1( 步中起作用,你不能得到比这更少的。

插入大小为 m 的std::set需要 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( 时间——与位字段不同,您不需要先验地知道潜在元素或结果的大小(尽管知道大小会有所帮助,因为您可以避免重新散列(。