我需要在std :: set中找到元素的索引。此索引可以显示为迭代器从头开始的距离。 一种方法可以是:
for(int i = 0, set<int>::iterator it = s.begin(); it != iteratorToBeFound; ++it, ++i);
这显然需要O(n)时间。但我们知道,在内部使用set实现的二叉搜索树中根的距离可以在O(log n)时间内找到。
他们以任何方式实现相同的方法来在C ++集中的O(log n)时间内找到索引吗?
答案 0 :(得分:4)
您可以使用函数std::set<>::find
搜索元素x
并计算distance到集合的第一个迭代器。
std::distance(s.begin(), s.find(x))
但是,正如注释所示,距离的运行时间取决于所使用的迭代器的类型。在set的情况下,这是一个双向迭代器,距离是O(n)。
答案 1 :(得分:3)
您可以使用已排序的std::vector<int>
。如果已排序,您可以在O(log n)
中找到元素。你可以在恒定时间内找到距离O(1)
。
按照排序的向量,我的意思是每次插入后(或多次插入后),你都会std::sort(v.begin(), v.end());
如果std::set<T>
中的类型不像int
那么轻 - 你可以保留 - std::set<T>
和迭代器std::vector<std::set<T>::iterator>
的有序向量。但保持这些结构同步并不容易。也许你可以在T
添加一些类似的位置?或者保持std::set<std::pair<T,int>, comp_first_of_pair<T>>
comp_first_of_pair
只需要set
仅按T
排序,第二int
用于保持位置设置?
只是一些想法 - 甚至有O(1)
距离时间......
答案 2 :(得分:1)
您不能将物联网用于双向迭代器。因此,唯一可接受的方法是自己计算(少于 int 少于插入集合中的X)。
但是,如果你已经将“数据收集”和“数据使用”阶段分开了 - 可能值得将 std :: set 替换为已排序的 std :: vector 。它更难维护,但有自己的好处,包括迭代器材料(因此你可以使用 std :: binary_search 进行O(log n)搜索,并与O(1)进行距离
答案 3 :(得分:1)
如果计算索引真的你的瓶颈,那么我会看到2个选项:
std::map
中。
当然,这意味着您必须更新此缓存。std::vector
。这并不像最初看起来那么糟糕。
如果您始终对矢量进行排序,则可以像set
一样使用它。
性能与set
类似。
最大的缺点是:节点可能被复制很多。
(这可以通过使用指针boost:shared_ptr
或std::unique_ptr
[仅限c ++ 11]来补偿)
std::lower_bound
的元素。 insert( lower_bound(b,e,x), x )
答案 4 :(得分:1)
您可以在O(log(N))中的一个有序集合https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/中找到一个元素的索引。这被实现为一棵红黑树。我知道这个主题很老,但是将来可能会对读者有所帮助。