我正在阅读:
“C ++标准库:Nicolai M.的教程和参考资料” 约祖蒂斯“
我正在关于套装& amp;多集。我遇到了关于插入和删除元素的一行:
“当使用多个时,插入和删除更快 元素,您对所有元素使用单个调用而不是多个元素 呼叫。“
我远不是数据结构大师,但我知道它们是用红黑树实现的。我不明白的是,STL实现者如何编写一个算法以更快的方式一次插入多个元素?
有人能说清楚为什么这句话对我来说是真的吗?
答案 0 :(得分:5)
我的第一个想法是,只有在插入/删除整个范围后才能重新平衡树。由于整个操作在实践中都是内联的,这似乎比函数调用的次数更多。
检查本地计算机上的GCC标头,似乎不是这种情况 - 无论如何,我不知道减少的重新平衡活动之间的权衡如何,以及可能增加中间插入到不平衡树的搜索时间,会工作。
也许它被认为是一个QoI问题,但无论如何,使用最具表现力的方法可能是最好的,不仅仅是因为它可以节省你编写for
循环并显示你的意图最多很明显,但是因为它让图书馆编写者在未来更加积极地进行优化,而无需您知道和更改代码。
答案 1 :(得分:1)
有两个原因:
1)对多个元素进行一次调用,而不是多次调用N次。
2)插入操作检查插入的每个元素是否已在容器中存在具有相同值的另一个元素。这可以在将多个元素组合在一起时进行优化。
答案 2 :(得分:1)
你所引用的内容是错误的。插入std::set
是O(log n),除非你使用位置迭代器insert()
重载,在这种情况下,当位置摊销 O(n)已验证。 但是,如果您使用范围重载与已排序元素然后,您将获得O(n)插入。
答案 3 :(得分:0)
内存管理可能是一个很好的理由。在这种情况下,它只能分配一次内存。如果所有元素都是单独调用的,则所有调用都会尝试单独分配内存。据我所知,大多数set
和map
实现都试图将内存保留在同一页面中,或者将页面放在一起以最小化页面错误。
答案 4 :(得分:-1)
我不确定这一点,但我认为如果插入的元素数量小于集合中元素的数量,那么在执行插入之前对插入的范围进行排序会更有效。这样,所有值都可以在树上单次传递,并且插入范围内的重复项可以很容易地消除(或者在多集合的情况下非常快地插入)。
当然,只有输入迭代器允许对输入范围进行排序(即它们是随机迭代器)时,才能进行此优化。