在C++中创建trie/后缀树时减少内存使用

Reducing memory usage while making a trie/suffix tree in C++

本文关键字:内存 后缀 C++ 创建 trie      更新时间:2023-10-16

我正在尝试用c++制作一个trie,现在我的基本数据结构是。。

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被使用如何改进

一些非常基本的建议:

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

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

使用邻接列表。

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

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

[{"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]},}

注意,索引-1中节点的next_state。我们有两个子节点——"e"answers"i"。

它非常高效且易于实现。然而,trie的操作将相当缓慢。