在ssd上创建trie。如何管理对象移动到其他位置?

时间:2012-07-10 16:40:25

标签: c# .net trie

我需要在ssd上创建一个trie。我不能使用太多RAM因为trie非常大,但是4 GB RAM没有问题。

目前我考虑采用以下方式:

  • 使用一个内存映射文件
  • 使用protobuf序列化对象,将指针更改为具有文件位置和长度的其他对象

现在我正在寻找可以提供帮助的工具。当对象(节点)变大时我遇到问题。我需要在该文件的文件中找到一个新位置,更改此对象的所有链接。然后我的档案中留下了一个空白。然后我需要压缩我的树并更改所有对象的所有位置以关闭一些间隙。在每个物体后留出一些空间会导致很大的空间需求。

您是否了解图书馆或有一些提示可以解决这个问题,或者可以帮助编程所有这些?

2 个答案:

答案 0 :(得分:1)

编辑:这是针对内存映射文件的方法,我真的很喜欢你的直觉。

Edit2 :每当我说“点”或“指针”时,我实际上是指从文件开头开始的从零开始的偏移量。由于书面数据永远不会移动,因此节点的位置充当它们的全局标识符。

虽然节点不应该变大。我这样做的方法就是让节点像:

  • 节点持有的字符(如果需要,编码为UTF-8)
  • 包含指向其子节点的8个项目的数组。这是静态标注NULL(或0),不再指定子项。这个列表永远不会变短,只会更大。
  • 指向一块内存的指针,该内存包含另一个子指针数组,也是静态标注的。你总是拥有这个,即使你实际上并不需要额外的空间,你也可以在里面写NULL
    • 如果指向实际有效内存,则在列表之后,如果需要,您将有另一个指向额外列表的指针,因此您可以走得更远。或者,第二个列表可以足以容纳所有字符。

作为替代方案,从一开始就为所有字符静态分配内存。但这可能会太快太快,具体取决于树的稀疏程度。

无论哪种方式,请注意,通过这种方式,您的实际节点大小永远不会增加,它具有静态长度。您可以根据需要在文件末尾添加额外的节点或额外的列表块,并在开头按住一个根指向其所有子节点,这样您就不必弄乱头部。

答案 1 :(得分:0)

我试图在这里为这个问题提供一个新角度:为什么不将trie-nodes存储在像SQLite这样的数据库中? SQLite快速,经过良好测试,功能丰富。它可能比你做得好得多。

关系数据库并不是真正存储树,但它们可以。通过编写自定义的磁盘数据结构,我无法想到任何可以解决的特定查询问题。