【问题标题】:Reducing memory usage while making a trie/suffix tree in C++在 C++ 中创建 trie/后缀树时减少内存使用
【发布时间】:2013-08-08 20:48:55
【问题描述】:

我正在尝试在 c++ 中进行尝试,现在我的基本数据结构看起来像..

struct node{
    int count; no of times this node has been visited.
    struct node* child[ALPHABET_SIZE]; // Let ALPHABET_SIZE be 26
}

当字符串变大时,会浪费大量分配的内存。就像我们插入 "he" 我们的树将是

root---->h--->e
    |--->e

我们看到在根目录中只有2/26th 分配的内存被使用了。 如何改进??

【问题讨论】:

    标签: c++ algorithm tree


    【解决方案1】:

    一些非常基本的建议:

    1. 如果您的分支因子预计较低,请考虑为子项使用数组以外的其他内容。例如,您可以有一个字母到 node* 对的数组,并对它们进行线性或二进制搜索(如果它们是有序的)。您也可以使用某种地图。
    2. 如果您不希望计数以百万/十亿为单位,您也可以使用较小的整数大小进行计数。
    3. 您可以从基于 arena 的分配器(即对象池)中获取节点,而不是动态分配节点,从而避免通常添加到堆上分配的对象的堆分配开销。

    【讨论】:

    • 我在尝试中看到的另一个技巧是拥有两种节点。一个“前缀”,这是他所拥有的,一个“后缀”,它只是“字符串的其余部分”并且没有孩子。 h->e->l 将有两个后缀节点,“p”和“lo”。根据您的工作方式,您可以通过这种方式节省大量空间
    • @MooingDuck 这是 Patricia trie 的一种特殊情况,其中只有一个子节点的节点(无论位置如何)都被折叠以消除链接开销?
    • @delnan:没听过这个名字,但是是的,基本上就是这样
    • 基于 arena 的分配器的另一个优点是,节点分配在内存中,从而更好地使用 CPU 缓存。
    • 我正在网上搜索相同的内容,这篇博文几乎解决了我的问题..blog.ivank.net/trie-in-as3.html
    【解决方案2】:

    不是为每个节点创建一个固定大小的数组,而是创建一个包含 1 个元素的数组并在插入子节点时调整它的大小(用大小+1 的新数组替换它)。插入会更慢,因此您可以测试并更改调整大小算法(size+1 或 size*2 或 size + size/2),以便在太慢时分配更少。

    【讨论】:

      【解决方案3】:

      使用adjacency list

      我们可以创建节点列表,而不是树。一个节点将是字典,每个都有“当前值”(字母表)和“下一个状态”(子节点的索引列表)。我们可以在节点中添加其他需要的属性。

      在您的情况下: 该列表将是 -

      [{"value":"", "next_state":[1 ]}, {"value":"h", "next_state":[2]}, {"value":"e", "next_state":[ ]}]

      现在说,我们添加“他的”。该列表将更新为:

      [{"value":"", "next_state": [1 ]}, {"value": "h", "next_state": [2 , 3]}, {"value":"e", "next_state":[ ]}, {"value":"i", "next_state":[4]}, {"value":"s", "next_state":[ ] },]

      注意,index-1 中节点的next_state。我们有两个子节点——“e”和“i”。

      它非常高效且易于实施。但是,trie 操作会慢很多。

      【讨论】:

        猜你喜欢
        • 2019-11-10
        • 2011-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-19
        • 1970-01-01
        • 2012-04-27
        相关资源
        最近更新 更多