哪个是实现trie节点的子节点 - 数组或散列映射的更好的实现?

时间:2016-09-15 19:52:04

标签: arrays algorithm data-structures hashmap trie

我正在阅读有关trie数据结构的内容,并发现了两个实现在trie节点中实现子节点的实现。以下是两种实现的细节: -

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

2)HashMap用于存储trie节点的子节点,其中字符为键,Trie节点为值。

请告诉我哪种实施更好,为什么?

3 个答案:

答案 0 :(得分:2)

这取决于 - 通常在记忆和速度之间进行权衡。

如果您的字符串很短并且您没有内存问题,那么当然可以选择阵列。这样可以加快搜索速度。如果你的字母在单词之间均匀分布,那也很好。

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

数组更快但可能比HashMap消耗更多内存 - 但不是必需的。想象一下,你的文字袋包含所有可能由26个字母组成的长度为N的26 ^ N个单词。然后HashMap会变慢并消耗更多内存。

答案 1 :(得分: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节点通常少于五个子节点,数组分配开销大于数组所拥有的数据。通过链表安排,您不会浪费任何记忆。

小孩子列表的连续搜索非常快,因为要搜索的孩子列表通常非常短,并且字母频率的分布通常非常偏斜。也就是说,前两个孩子的使用频率通常比其他孩子高得多。因此,平均而言,您只需要搜索两个或三个子节点。

其中任何一个都可以节省大量内存,这可以使程序更快。在使用这些替代结构时,我的测试没有显示出明显的性能损失。

答案 2 :(得分:1)

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

当字母较大且使用的键的实际数量较少时,hashmap的内存较少,但是hashmap本身的结构比数组的内存更多。因此需要权衡取舍,并取决于实际的特里树琴键。

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