我需要在内存中保留一些关于可能大量文件和目录的数据(通常高达几十万)。显而易见的方法是使用以路径为键的Dictionary<string, Something>
,但这有两个问题:
此问题似乎是使用前缀树(或trie)的良好候选者,路径段为“字符”。我试图实现它,并且前缀查找的性能也不错(大约比字典快4倍),但它有两个问题:
我确定它一定是一个非常常见的问题,所以也许有一些我不知道的众所周知的解决方案?
答案 0 :(得分:2)
只是一些通用的想法:
首先,Patricia trie可能是提高尝试内存消耗的最着名的方法 - 它压缩了所有节点将一个子节点放入一个节点的路径,并沿着路径连接字符。还有一个版本,您可以将数据视为二进制数字序列,其优点是您总是最多有2个子节点,并且它也更容易实现。
其次,内存消耗实际上取决于您如何存储给定节点的子节点 - 您是否维护了256个节点的数组?这通常是直接查找的最有效方式,但是如果需要遍历所有子节点,它也会消耗最多的内存并且速度很慢。其他选择是:
存储一对数组(letter, child node)
- 这可能是内存效率最高的,因为它只存储您真正关心的对象,并且在迭代所有子节点方面也具有良好的性能。但是,您必须检查所有对直接查找 - 通常距离根更远,但可能是根目录附近的问题。
在将字母映射到子节点的每个节点中存储某种字典。这在性能方面是最平衡的 - 它为所有操作提供了相当好的速度,并且具有一定的内存效率。
此外,如果你预先构建整个集合然后只是查询它,有一种方法可以存储基于Tarjan tables的子链接,这可能会增加构造时间,但会节省内存和查询时间过了。
答案 1 :(得分:-1)
前缀树怎么样的方法。即如果你想存储
/root/x
/root/a/b
/root/a/c
/root/a/d
/root/a/e
/root/a/c/e
/root/a/c/f
Here is how your tree will look like.
root
/ \
x __ a __
/ / \ \
b c d e
/ \
e f
它将节省空间,因为每个目录名称只会存储一次。 搜索和插入也将是O(log(n))