【问题标题】:Which is a better implementation to implement a trie node's children - array or hashmap?哪个是实现 trie 节点的子节点的更好实现 - 数组或哈希图?
【发布时间】:2017-01-23 23:06:17
【问题描述】:

我正在阅读有关 trie 数据结构的信息,并找到了两种实现方式来实现 trie 节点中的子节点。以下是两种实现的详细信息:-

1) 长度为 26 的 Trie 节点数组已用于存储 trie 节点的子节点。

2) HashMap 用于存储以字符为键、以Trie 节点为值的trie 节点的子节点。

请告诉我哪个实现更好,为什么?

【问题讨论】:

  • 我建议你同时实现它们并比较它们。

标签: arrays algorithm data-structures hashmap trie


【解决方案1】:

这取决于 - 内存和速度之间的通常权衡。

如果您的字符串很短并且您没有内存问题,那么当然可以使用数组。通过这种方式,您可以更快地进行搜索。如果您的字母在单词之间均匀分布,那也很好。

如果您的字符串可能很大并且有些字母很少出现,那么请使用哈希映射。这样你就不会占用太多未使用的内存。如果您的字母表远大于 26 个字母,那就更好了。

Array 比 HashMap 更快,但可能会消耗更多内存 - 但不是必需的。想象一下,你的词袋包含所有可能的 26^N 个长度为 N 的词,它们可以由 26 个字母组成。那么 HashMap 会更慢并且消耗更多的内存。

【讨论】:

    【解决方案2】:

    trie 节点有两种非常常用的结构:

    CharNode
        char letter
        CharNode[26] children
    
    CharNode
        char letter
        Dictionary<char, CharNode> children
    

    它们运行良好,但它们浪费了大量内存,因为子列表非常稀疏。在我看来,两者都没有提供抵消内存成本的性能优势。我更喜欢使用:

    CharNode
        char letter
        CharNode[] children
    

    或

    CharNode
        char letter
        CharNode* firstChild
        CharNode* sibling
    

    在第一种情况下,children 数组的大小是可变的,以仅容纳实际使用的子项数量,并且子项按最常用的字母排列在最前面。顺序搜索找到所需的孩子。

    在第二种情况下,你有一个孩子的链表,每个孩子都有一个兄弟指针。同样,孩子在列表中是根据频率排列的。

    我更喜欢第二种,因为在许多运行时环境中分配数组的成本相当高。例如,在 .NET 中,数组分配开销大约为 50 个字节。考虑到一个 trie 节点的子节点通常少于 5 个,因此数组分配开销大于数组所保存的数据。使用链表排列,不会浪费任何内存。

    小孩子列表的顺序搜索非常快,因为要搜索的孩子列表通常很短,字母频率的分布通常很倾斜。也就是说,前两个孩子的使用频率通常远高于其他孩子。因此,平均而言,您只需搜索两个或三个子节点。

    这两种方法都可以节省大量内存,从而使程序更快。我的测试并没有显示出使用这些替代结构对性能有明显影响。

    【讨论】:

    • 我不确定您使用的是什么语言/实现,但为什么字典会浪费内存?它不是只会在您添加新条目时填满吗?在您提出的方案中,尚不清楚您如何跟踪最常用的字母。您是否需要额外的数据结构或额外的字段来跟踪这一点?
    • @LorenzForvang 字典的开销很大。例如,在 C# 中,字典中的每个键/值对至少有 16 个字节的开销。当您开始谈论数亿个节点时,这会变得很昂贵。构建 trie 时会计算最常用的字母。我对 Try 的典型用法是构建静态 trie。但您也可以在运行时执行此操作:您只需要跟踪字符频率。
    【解决方案3】:

    数组是经典的教科书实现,默认选择。

    hashmap 消耗更少的内存,当字母很大并且实际使用的键数相对较少时。但是 hashmap 本身的结构比数组消耗更多的内存。所以它是折衷的,取决于实际的 trie 键。

    每个子链接的访问速度几乎相同 O(1)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-28
      • 2018-03-01
      相关资源
      最近更新 更多