在C ++中有什么类似Haskell Data.Sequence的吗?

时间:2018-01-07 17:53:01

标签: c++ haskell data-structures tree

是否有C++库实现Haskell Data.Sequence容器之类的内容?

我最感兴趣的是:

  1. 维护元素顺序(插入它们)。
  2. O(logn)通过索引访问。阿卡operator[](size_type pos)
  3. O(logn)插入/删除中间(通过索引)。

1 个答案:

答案 0 :(得分:4)

在我看来,实现这种数据结构的方法需要一个存储每个节点中元素数量的树。它允许在O(log(N))中插入和检索,并且通过计算树中给定节点的“左”有多少元素来维护索引。

* 我在这里回答的可能是一个稍微不同的问题,实际的问题是要求提供一个库的建议,这在SO上是明确的偏离主题。

此树的节点如下所示:

template<typename T>
struct Node {
  Node* left;
  Node* right;
  size_t elements;
  T value

  T& access(size_t index) {
    if (left->elements == index) {
      return value;
    } else if (left->elements > index) {
      return left->access(index);
    } else {
      return right->access(index - left->elements - 1);
    }
  }

  void insert(size_t index, T&& value) {
    // insert `value` at right place, increment `elements`
  }
}

(我将insert方法作为练习留给了读者。)

编辑:正如下面评论中提到的willir(OP),树需要是一棵平衡的树。 Arne Vogel认为B树将是缓存局部性的最佳选择。

可是:

如果你实现了类似的功能,请确保测量应用程序,并将其与std::vector进行比较。在任意位置插入向量是O(N),而不是O(log(N)),但它是非常廉价操作的O(N)。与这样的数据结构相比,向量具有许多优点:

  1. 无法维护代码。

  2. 要存储的东西少(在树中需要存储两个指针和一个计数,这在向量中是不必要的),这意味着更多的数据同时适合缓存。

  3. 始终按照存储数据的顺序访问数据。对于树,您需要遍历可以存储在内存中任意位置的节点,它们不需要靠近在一起,并且可能不会按照它们被读取的顺序存储。

  4. 第2点和第3点意味着向量具有许多更少的缓存未命中。这可能会导致时间上的巨大差异。

    如果每个数据元素都很大,那么在向量中移动数据会变得相当慢。但是在这种情况下,您应该在向量中保留指向数据的指针,这样您就可以移动指针列表,而不是实际数据。对于这样的大数据元素,我建议单独分配每个元素,并将其指针保持在std::vector<std::unique_ptr<T>>

    以下是一些相关链接: