您将使用什么样的数据结构来实现像结构这样的大型持久数组(大小> 10 Mio元素)
数据结构的接口应支持以下操作:
YType get(IdxType idx) // random access
void insertIdx(IdxType idx, YType yValue) // random insert
void deleteIdx(IdxType idx) // random delete
让索引IdxType
为标量无符号值,例如unsigned long long
和YType
标量值或结构。
这些操作的复杂性永远不应该大于O(log n),如果随机访问的复杂性在一段时间后会降至O(1),那将非常有效,因为对于许多用例,读操作将是最常用的。
这些要求排除了可以写入光盘的内存数据结构,例如向量或列表,因为向量的插入复杂度是O(n),列表的随机访问也是O(n)。
修改:
请注意,具有索引键的数据结构的哈希映射或树不符合要求。某个索引的值可以更改。即,当插入索引的值时,所有后续索引都改变它们的值。这正是插入元素时数组中后续索引所发生的情况。
答案 0 :(得分:0)
您可能希望使用订单统计树,即支持O(log n)插入,删除和查找的树数据结构。通常,订单统计树用于存储已排序的数据,但修改它们以存储未排序的序列相对简单。
直观地,订单统计树是二叉树,其中每个节点在其左子树中存储子节点的数量。这样,您可以按如下方式递归查找第n个元素:
要在节点n之前进行插入,请使用相同的过程查找第n个节点,并将新值插入到前一个节点中的节点(向左移动,然后继续向右,直到离开树并在那里插入节点) 。然后从第n个元素向上向上走回树,并调整插入路径上需要更新的所有节点的k值。
为防止树太不平衡,您可以使用任何标准树平衡方案(AVL,红/黑等)将高度保持在O(log n)。这为数据结构上的所有操作提供了O(log n)性能。
希望这有帮助!
答案 1 :(得分:0)
取决于您是否需要并发访问它...
如果您只需要一个可以在任何给定时间访问它的客户端应用程序,请使用内存结构,例如rope(或者甚至只是带有“数组”索引的哈希表作为键),提供访问和修改复杂性之间的良好平衡。完成后,将其序列化为一个简单的文件。 RAM现在很便宜且很丰富,10 M元素应该适合它,除非每个元素都非常大。
如果您需要并发访问,则事务等使用数据库。你的“数组”实际上是一个B树,其键是数组索引。如果您的DBMS支持,请使用clustering消除“不必要的”表堆并将所有内容保留在B树中。像这样:
CREATE TABLE THE_ARRAY (
INDEX INT PRIMARY KEY,
DATA VARCHAR(50) -- Whatever...
) ORGRANIZATION INDEX
(ORGRANIZATION INDEX是其他DBMS中所谓的“集群”的特定于Oracle的语法;使用适合您的DBMS的任何语法。)
插入将是O(N)(因为您需要在插入后更新索引)并且查找将是O(log(N))。此外,一些DBMS支持哈希索引,这应该允许O(1)查找,但插入可能比B树更糟。