Tries对现代建筑仍然是一个好主意吗?

时间:2009-03-09 00:07:17

标签: data-structures trie

我最喜欢的大学数据结构之一是Trie。如果共享前缀,它是一个很好的数据结构,用于保存大量字符串。查找也很好,因为它们是在字符串的O(| length |)处完成的,无论集合中有多少字符串。

相比之下,平衡树在设定项目数量中将为O(log N),加上您为比较支付的费用。哈希表将涉及哈希计算,比较等。

令我感到惊讶的是there is no Trie implementation in the standard library of most languages

我能想到的唯一原因是内存访问成本太高的可能性。如果进行树查找,则不是在调查O(log N)位置,而是在进行O(| length |)不同的位置,并产生所有后果。如果字符串很长,这可能会导致太多。

所以我想知道:我刚刚描述的问题是多少?当您需要存储大型字符串或字符串映射时,您会怎么做?

5 个答案:

答案 0 :(得分:7)

之前我没有想到这是一个值得关注的领域,但是现在您提到它,有时候标准的Trie实现可能会很方便。另一方面,据我所知,Tries由Python和Perl以及我现在使用的其他字符串精通语言使用。

最后我检查过,很久以前,BSD内核代码在代码中使用Tries(Patricia Tries)来选择发送数据包的最佳接口。看起来像Wikipedia has some info

答案 1 :(得分:4)

您可以构建两个示例应用,看看哪个应用效果更好。假设您没有页面错误,内存访问很便宜。然后它非常昂贵。对于客户端应用程序开发,由于这个原因,它几乎总是比访问内存更好。现代处理器速度非常快,但缓存未命中仍然受到影响。

答案 2 :(得分:2)

我在C#中使用Trie和Dictionary(强类型哈希表)进行了一些性能测试。我发现字典比Trie快5-10倍。也许我对Trie的实现可以进行一些优化,但不足以比字典快得多(或者甚至可能更快)。

字典中的ContainsKey方法接近于O(1)操作(取决于散列算法的好坏程度),因此只要散列算法相当快,就不容易使集合胜过它。

使用自定义IEqualityComparer,您可以将大多数内容用作词典中的键,这使得它非常灵活。 Trie在您可以用作键的方面有点受限,因此在某种程度上限制了有用性。

答案 3 :(得分:0)

尝试对于 IP 地址和子网查找特别有用,并且始终适用于任何架构。您可以在 The open-source IPAddress Java library 中找到地址的 trie 实现。免责声明:我是那个图书馆的项目经理。

尝试按地址前缀组织,如本例所示:

options = ['A', 'B', 'C', 'D'] # if you want more options use string.ascii_uppercase
questions = {"How many lives do cat's have?": ['9', ['9', '1', '10']], "Is this working now?": ['Yes!', ['Yes!', 'No!', 'Maybe...']]}
question = random.choice(list(questions.keys()))
data = questions.get(question)
answer_options = data[1].copy()
random.shuffle(answer_options)
answer = data[0]
answer_option = options[answer_options.index(answer)] #gets correct option from options
answer_msg = ""
for i, option in enumerate(answer_options):
   answer_msg += f"{options[i]}) {option}"
#check if user input is equal to answer_option

该结构允许高效的查找、路由和包含检查。

答案 4 :(得分:0)

很难让标准的 Trie 类具有广泛的用途,足以证明将其放入标准库是合理的。

当然,它需要你放入任何东西来实现一个通用的类似字符串的接口。

并且由于 Trie 实际上并不存储字符串,因此遍历它要么很慢,因为它必须重新构造所有元素,要么很笨拙,因为您实际上并没有得到字符串。

而且,你知道,average_length 和 max_length 都至少是 O(log N)。如果您知道元素是字符串,那么您可以在 O(length + log N) 中搜索 BST,这与 O(length) 几乎相同,并且您保留了实际在结构中包含字符串的优势。

实际上,Tries 获胜的唯一事情是具有长公共前缀的字符串的内存高效存储。它发生了,但并不常见。我想没有一种语言认为它值得麻烦,包括一种。