是否有支持以下操作的boost / stl容器?

时间:2014-04-15 19:38:03

标签: c++ c++11 boost stl

我一直在寻找能提供以下功能的stl / boost容器:

  1. 按排序顺序自动插入元素。 (记录n)
  2. 从起始节点返回元素的索引/深度。 (记录n)
  3. 如果没有,那么实现这一目标的最佳方法是什么?我正在考虑使用双链接列表的解决方案。这是解决这个问题的好选择吗?

3 个答案:

答案 0 :(得分:4)

<强>更新

您需要order statistic tree。 C ++标准库没有,也没有提供实现的方法,参见

也没有提升,请参阅Future work和上面链接的问题。

然而,好消息是,libstdc++中有这样的树作为扩展名提供!


(原答案:)

  
      
  1. 按排序顺序自动插入元素。 (记录n)
  2.   
  3. 从起始节点返回元素的索引/深度。 (记录n)
  4.   

在我看来,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::mapstd::set根据标准保证 O(log(N))插入和搜索,它们也满足排序顺序条件。请参阅section 23.4的C ++标准。

@StefanoSanfilippo建设性评论后更新

但请记住,这些容器只允许使用唯一的键/元素。如果您有多个值,则必须使用std::multimapstd::multiset。这些容器与std::mapstd::set具有几乎相同的属性,但允许多个键/元素。

现在关于索引/深度问题,就STL容器问题而言,不能保证std::mapstd::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。

请注意,链表有线性插入时间,即使是双倍。