是否有C++
库实现Haskell
Data.Sequence
容器之类的内容?
我最感兴趣的是:
O(logn)
通过索引访问。阿卡operator[](size_type pos)
。O(logn)
插入/删除中间(通过索引)。答案 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)。与这样的数据结构相比,向量具有许多优点:
无法维护代码。
要存储的东西少(在树中需要存储两个指针和一个计数,这在向量中是不必要的),这意味着更多的数据同时适合缓存。
始终按照存储数据的顺序访问数据。对于树,您需要遍历可以存储在内存中任意位置的节点,它们不需要靠近在一起,并且可能不会按照它们被读取的顺序存储。
第2点和第3点意味着向量具有许多更少的缓存未命中。这可能会导致时间上的巨大差异。
如果每个数据元素都很大,那么在向量中移动数据会变得相当慢。但是在这种情况下,您应该在向量中保留指向数据的指针,这样您就可以移动指针列表,而不是实际数据。对于这样的大数据元素,我建议单独分配每个元素,并将其指针保持在std::vector<std::unique_ptr<T>>
。
以下是一些相关链接: