我一直在寻找能提供以下功能的stl / boost容器:
如果没有,那么实现这一目标的最佳方法是什么?我正在考虑使用双链接列表的解决方案。这是解决这个问题的好选择吗?
答案 0 :(得分:4)
<强>更新强>
您需要order statistic tree。 C ++标准库没有,也没有提供实现的方法,参见
也没有提升,请参阅Future work和上面链接的问题。
然而,好消息是,libstdc++
中有这样的树作为扩展名提供!
(原答案:)
- 按排序顺序自动插入元素。 (记录n)
- 从起始节点返回元素的索引/深度。 (记录n)
醇>
在我看来,C ++标准库和boost都没有提供一个能够提供开箱即用的复杂性保证的容器。您要么必须自己实现此容器,要么放宽复杂性要求,并且至少允许其中一个容器{/ 1}}。
如果没有:实现这一目标的最佳方法是什么?我在想 使用双链表的解决方案。解决这个问题会是不错的选择 问题?
O(n)
是一个双向链接列表,但您只能实现线性时间插入。由于缓存使用不当,std::list
是一个重要的性能杀手。
使用boost::container::flat_set
可能会更好,它也只提供线性时间插入,但由于优化使用缓存(由于硬件预取器),它仍然可能会让您惊讶于它的速度。作为奖励,您可以获得随机访问迭代器,因此如果您已经拥有该元素,则可以在std::list
时间找到该索引。
如果两个复杂性要求都是必须的,那么我没有看到比实现自平衡二叉搜索树更简单的方法,并且还在每个父节点上存储子树大小。维护这些额外信息不会破坏O(1)
复杂性。即使您从O(log n)
std::map
的{{3}}实施开始,也是实现它的重要且非平凡的工作(不保证是红黑树,但在libstdc++
中是,它是开源的。
还有一件事想到:你的使用模式是什么?您是否完全随机地进行插入和索引查找,一个接一个?如果不是,或者至少主要不是,那么你可以在两者之间切换数据结构并使用stl或boost容器之一。
答案 1 :(得分:3)
std::map
和std::set
根据标准保证 O(log(N))插入和搜索,它们也满足排序顺序条件。请参阅section 23.4的C ++标准。
@StefanoSanfilippo建设性评论后更新:
但请记住,这些容器只允许使用唯一的键/元素。如果您有多个值,则必须使用std::multimap
和std::multiset
。这些容器与std::map
和std::set
具有几乎相同的属性,但允许多个键/元素。
现在关于索引/深度问题,就STL容器问题而言,不能保证std::map
和std::set
被实现为二叉树,因此没有用于访问树属性的接口例如深度和指数(请参阅How to find the depth of each node in std::map?)。做出有根据的猜测,我认为像容器这样的boost树也是如此。
更新 - 引自@Mooing Duck的评论:
提升树也没有办法获得索引。
答案 2 :(得分:0)
二叉树(B-tree)在平均情况下具有对数插入和检索(相当于深度计数)时间,并且在按顺序行走时自然排序。
不幸的是,如果树不平衡(最坏情况),B树插入/检索时间可能会退化为线性。如果这是一个问题,你应该考虑一个红黑树,这不会消除问题,但会减少它,同时保持插入时间的对数与树的大小。
STL和Boost都没有实现B或RB树,尽管std::map
通常实现为RB。
请注意,链表有线性插入时间,即使是双倍。