std :: set :: insert,我有多糟糕提示?

时间:2011-07-08 16:02:20

标签: c++

我在std::pair<int, int>中进行了大量std::set的插入操作,并且花费的时间比我想要的要长。当我编写代码时,我认为如果事实证明它是一个瓶颈,我将在稍后使用提示迭代器形式的insert;好吧,现在它被描述了, 是一个瓶颈。所以我想使用迭代器提示。

然而,我并不总是知道插入我的对的好位置。我通常批量插入它们(在这种情况下批量大约占总输入大小的0.01%,包括重复)增加的设置顺序,但是当插入批次时,我不知道下一个应该在哪里开始。如何使用提示?插入是否从建议的位置执行二分搜索?通常情况下,使用不良提示有多糟糕?

4 个答案:

答案 0 :(得分:5)

我建议只阅读编译器读取的内容:#include <set>的头文件。在我的系统(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); }

外卖:

  1. 糟糕的提示不会导致效率上升
  2. 插入时间为O(log n)
  3. 您可以阅读有关insertion hints in the GNU libstdc++ manual
  4. 的更多信息

答案 1 :(得分:2)

如果你检查文件bits/stl_tree.h(在GNU libstdc ++中),你会发现带有提示参数的_M_insert_unique成员函数看起来在提示左边的一个节点,然后是一个节点到右边,然后默认调用普通插入例程。

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

因此,糟糕的提示有多糟糕取决于比较例程,以及std::set的分配器是否将节点打包在内存中。

答案 2 :(得分:0)

如果是提示 - 用于插入的位置,则提示很好。例如,如果按顺序插入对象,则可以正常工作。

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

答案 3 :(得分:0)

如果您在使用之前一次性构建该集合,则可以使用向量代替并在使用之前对其进行排序。您可以在排序后的向量上使用binary_searchlower_boundupper_boundequal_range算法进行快速查找。您还可以使用mergeinplace_merge来组合已排序的向量,并使用set_differenceset_intersectionset_union来执行其他常见的集合操作。

相关问题