trie树(字典树)

        上学期的一门编程课写过几个实验程序,可惜由于懒散、能力等各方面问题,写得都很粗糙,比如这个trie树只是做了基本的实现,至多有一点点小技巧,性能其实很差。但还是写点东西记录一下,也是成长过程的一部分。

        百度百科上说trie树是哈希树的变种,哈希树我没研究过,但trie的特点很明显,确实使用了哈希的思想。通常的查找都是基于比较的,而哈希的思想是在键和值之间建立某种映射,通过键来查找到值。关于哈希的资料有很多,在此不赘述。本文重在讲解trie树。

        如果想在一大堆字符串中找到某个特定的字符串,最简单的方法当然是暴力匹配,然而效率会低得吓人,即使对于中等规模的数据量,其性能也是无法接受的。而trie树采取了以空间换时间的策略(增加了一些指针域等额外数据,但也未必会增加存储空间,例如有大量字符串,每个字符串长度为n个字符,前n-1个字符都是一样的,只有最后一个字符不同,那么采用特定实现的trie树反而会大大节省存储空间),大大提高了字符串匹配的速度,实现得当的话,复杂度与欲查找的字符串长度成比例,相对于暴力匹配,很明显是一个巨大的优化。

       那么,是如何实现的呢?暴力匹配之所以慢,是因为做了许多重复工作。例如,欲在{"aaaa", "bbb", "abd", "abcd"}查找“abcd"字符串,暴力匹配首先将第一个字符串"aaaa"与"abcd"比较,一个一个字符判断是否相同,第一个字符相同就判断第二个,依此类推,直到匹配成功或者某个字符不同匹配失败。然后继续匹配第二个字符串"bbbb",我们将"abcd"的第一个字符'a'与其首字母'b'比较时,发现两者不同,匹配失败,再继续匹配第三个字符串。但是等等,我们为什么要做这第二次比较呢?在与第一个字符串匹配时,我们已经知道了欲查找字符串"abcd"的首字母为'a',那么,所有首字母不为'a'的字符串都可以排除了,无须匹配,所以,第二次匹配是在做无用功。你可能会说,我不匹配怎么知道某个字符串首字母不是'a',不还是要进行匹配的嘛。于是,我们就需要先对原始数据做一些处理,提取出某些信息,方便查找。建立trie树就是这个目的,根据每个字符串的各个字母,将其划分为不同的集合,这样就缩小了范围。例如,对于"abd"字符串,当第一个字符是'a',我们将其存入首字母为'a'的字符串集合里,第二个字符是'b',我们再将其存入(首字母为'a')第二个字符为'b'的集合里,依此类推。trie树建立完成后,查找"abcd"字符串,根据字符串中每个字符进入相应的集合去寻找,当发现首字母为'a'时,就去首字母为'a'的集合里匹配,"bbbb"字符串存储在另一个集合里,无须匹配,避免了无用功,提升了效率。当然这里所说的集合等只是一个抽象的概念,具体实现时trie树顾名思义当然是一棵树,首字母为'a'的集合是指以相应节点为根的子树。



       如上图,当确定首字母为'a'后,我们只需选择最左边的那棵子树继续向下匹配,其余子树不必理会。

       在实现时,数据是保存在节点中,而不是如图中那样,似乎是保存在边上的。在树中,这些边代表指针,一般无法保存额外信息。trie树其实是一种概念,具体实现有多种方法,甚至可以不是一棵树,其中一种常见的实现方式是双数组实现,用两个数组而不是树来实现trie“树”。如果用树这种数据结构来实现的的话,很明显的实现方法就是在树的节点中保存字符。这里又有两种选择:第一种是在节点中用数组或链表只保存出现过的字符,查找时须遍历,速度较慢,但节省空间;第二种是用哈希表的形式保存字符,速度较快,但占用空间较大,尤其是在字符集很大的情况下。trie树本来就是用于处理大量字符串的,并且常常需要很多空间开销来换取时间,所以不宜再加大空间开销。

         trie树-github

         trie树-OSChina

         这是一个简单的实现,分别上传到了github和OSChina,性能较低。有很多优化方法,但会掩盖基本思想,讨论trie树的高效实现和优化不是本文的目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值