C++ std::set::insert,我能暗示多坏?

C++ std::set::insert,我能暗示多坏?,c++,C++,我正在做大量的std::pair插入到std::set中,所花的时间比我想要的要长。当我编写代码时,我想如果它最终成为一个瓶颈,我会考虑使用insert的提示迭代器形式;好吧,现在它被分析了,它是一个瓶颈。所以我想使用迭代器提示 然而,我并不总是知道插入配对的好位置。我通常会按递增的集合顺序分批插入它们(在本例中,一个批次的大小约为总输入大小的0.01%,包括重复项),但插入一个批次时,我不知道下一个批次应从何处开始。如何使用提示?insert是否执行类似于从建议位置进行二进制搜索的操作?通常,

我正在做大量的
std::pair
插入到
std::set
中,所花的时间比我想要的要长。当我编写代码时,我想如果它最终成为一个瓶颈,我会考虑使用insert的提示迭代器形式;好吧,现在它被分析了,它是一个瓶颈。所以我想使用迭代器提示


然而,我并不总是知道插入配对的好位置。我通常会按递增的集合顺序分批插入它们(在本例中,一个批次的大小约为总输入大小的0.01%,包括重复项),但插入一个批次时,我不知道下一个批次应从何处开始。如何使用提示?insert是否执行类似于从建议位置进行二进制搜索的操作?通常,使用错误提示会有多糟糕?

我建议只阅读编译器阅读的内容:include的头文件。在我的系统(GNU libstdc++4.5.1)上,我可以阅读以下自解释文本:

  /**
   *  @brief Attempts to insert an element into the %set.
   *  @param  position  An iterator that serves as a hint as to where the
   *                    element should be inserted.
   *  @param  x  Element to be inserted.
   *  @return  An iterator that points to the element with key of @a x (may
   *           or may not be the element passed in).
   *
   *  This function is not concerned about whether the insertion took place,
   *  and thus does not return a boolean like the single-argument insert()
   *  does.  Note that the first parameter is only a hint and can
   *  potentially improve the performance of the insertion process.  A bad
   *  hint would cause no gains in efficiency.
   *
   *  For more on @a hinting, see:
   *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt07ch17.html
   *  
   *  Insertion requires logarithmic time (if the hint is not taken).
   */
  iterator
  insert(iterator __position, const value_type& __x)
  { return _M_t._M_insert_unique_(__position, __x); }
外卖:

  • 一个不好的提示不会提高效率
  • 插入是
    O(日志n)
  • 你可以阅读更多关于

  • 如果提示是正确的,那么提示就是好的——插入的位置。例如,如果按顺序插入对象,则可以使用


    如果提示不正确,则无效,您将得到一个非提示的插入。

    如果您检查文件
    bits/stl_tree.h
    (在GNU libstdc++),您将发现带有提示参数的
    \u M_insert_unique
    成员函数在提示的左侧显示一个节点,然后在右侧显示一个节点,然后默认调用普通的插入例程

    它调用
    键\u compare
    至少一次(如果集合不是空的),最多三次。从一个节点到下一个或上一个节点是一个跟随指针的问题,因为(IIRC)
    std::set
    和朋友都是


    因此,错误提示的严重程度取决于比较例程,以及
    std::set
    的分配器是否在内存中关闭节点。

    如果在使用集合之前一次构建集合,则可以使用向量,并在使用集合之前对其进行排序。您可以在排序向量上使用
    二进制搜索
    下限
    上限
    ,以及
    相等范围
    算法进行快速查找。您还可以使用
    merge
    inplace\u merge
    组合已排序的向量,
    set\u difference
    set\u intersection
    set\u union
    执行其他常见的集合操作。

    比我想要的长吗?我知道
    O(n)
    O(logn)
    ,甚至
    O(n^2)
    。。。但是
    O(比我想要的长)
    不在我的文本书中。嗯,事情也很少需要
    O(logn)
    秒。。。但进行约200000次插入(重复)大约需要4秒钟。这对用户来说是一个明显的延迟,如果这是一个瓶颈,您可以使用
    unordered\u set
    进行基准测试,我想缩短它。Boost或STL取决于您的编译器。嗯,因此,如果提示不完全正确,它可能会被完全忽略?您必须在这里阅读字里行间的内容。如果提示被证明是错误的,它可能会返回并立即调用未提示的版本-但这并没有明确说明。@carlpett:是的,可能。你的C++实现在理论上可以做一些更聪明的事情(不可能,但可能);如果您指定了实际的编译器和版本,可能会有人给出明确的答案。链接断开了,是吗?@doug65536看起来是这样。答案文本已编辑为指向回程机器:)