【发布时间】:2018-05-02 17:54:10
【问题描述】:
std::set 是一个排序树。它提供了begin 和end 方法,因此我可以获得最小值和最大值以及lower_bound 和upper_bound 进行二分搜索。但是,如果我想让迭代器指向中间元素(或者如果那里有偶数个元素,则其中之一)怎么办?
有没有一种有效的方法(O(log(size)) 而不是O(size))来做到这一点?
{1} => 1
{1,2} => 1 or 2
{1,2,3} => 2
{1,2,3,4} => 2 or 3 (but in the same direction from middle as for {1,2})
{1,312,10000,14000,152333} => 10000
【问题讨论】:
-
排序二叉树可能并且通常是 std::set 的实现细节,但这不是必需的。如果您需要排序数组或二叉树,那么最好使用您需要的。
-
@ÖöTiib,我需要动态插入元素并获得集合的中间位置。排序的数组/向量将导致插入为
O(n),但我希望插入和查询都可以工作O(lb(n))。我知道带有隐式键的 Decart 树允许这样做,但我不想实现它,并希望std::set足以实现这一点。 -
@Qwertiy 在大多数用例中,由于缓存局部性,插入向量会非常快。
std::set和链表一样,使用指向分散在各处的子元素的指针,因此在很多情况下它可能会比较慢。阅读Why you should never, ever, EVER use linked-list in your code again、Bjarne Stroustrup: Why you should avoid Linked Lists、Are lists evil? -
您真的需要排序元素还是只需要最小、最大和中值?在后一种情况下,请考虑使用
std::nth_element和std::vector。 -
@DDrmmr,我只需要中等,但需要对数来获得它,而不是完整扫描。目前我认为保留对应迭代器的想法是最好的。