大持久数组结构

时间:2013-01-04 16:28:19

标签: database-design data-structures

您将使用什么样的数据结构来实现像结构这样的大型持久数组(大小> 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 longYType标量值或结构。

这些操作的复杂性永远不应该大于O(log n),如果随机访问的复杂性在一段时间后会降至O(1),那将非常有效,因为对于许多用例,读操作将是最常用的。

这些要求排除了可以写入光盘的内存数据结构,例如向量或列表,因为向量的插入复杂度是O(n),列表的随机访问也是O(n)。

修改
请注意,具有索引键的数据结构的哈希映射或树不符合要求。某个索引的值可以更改。即,当插入索引的值时,所有后续索引都改变它们的值。这正是插入元素时数组中后续索引所发生的情况。

2 个答案:

答案 0 :(得分:0)

您可能希望使用订单统计树,即支持O(log n)插入,删除和查找的树数据结构。通常,订单统计树用于存储已排序的数据,但修改它们以存储未排序的序列相对简单。

直观地,订单统计树是二叉树,其中每个节点在其左子树中存储子节点的数量。这样,您可以按如下方式递归查找第n个元素:

  1. 如果树为空,则没有元素。
  2. 如果n小于或等于左子树中的元素数(称之为I),则递归查找左子树中的元素。
  3. 如果n = k + 1,则树的根是第n个元素。
  4. 否则,在右子树中查找n - k - 1st元素。
  5. 要在节点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树更糟。