二叉树--trie树

闲来无事,写写博客,总结一下trie树;

算法原理

首先,让我们对trie树来一个比较直观的认识,下面的这个例子,大家应该都能够理解。
下面我们有and,as,at,cn,com这些关键词,那么如何构建trie树呢?

这里写图片描述

在上面这个棵树中,树的根节点没有存储任何的数据,就只是root,而将这些单词按照相同前缀,分支节点的顺序进行存储,这样有一个好处就是,相同前缀的单词的前缀我只需要存储一次就可以了,遍历树的每一个“树枝”,都会得到相对应的单词。这就是trie树的基本原理。

第一:根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
第二:从根节点到某一节点,路径上经过的字符连接起来,就是该节点对应的字符串。
第三:每个单词的公共前缀作为一个字符节点保存。

利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。

trie的分类

Trie 树, 又称字典树,单词查找树。它来源于retrieval(检索)中取中间四个字符构成(读音同try)。用于存储大量的字符串以便支持快速模式匹配。主要应用在信息检索领域。

Trie 有三种结构: 标准trie (standard trie)、压缩trie、后缀trie(suffix trie) 。

1. 标准Trie (standard trie)

标准 Trie树的结构 : 所有含有公共前缀的字符串将挂在树中同一个结点下。实际上trie简明的存储了存在于串集合中的所有公共前缀。 假如有这样一个字符串集合X{bear,bell,bid,bull,buy,sell,stock,stop}。它的标准Trie树如下图:

这里写图片描述

上图(蓝色圆形结点为内部结点,红色方形结点为外部结点),我们可以很清楚的看到字符串集合X构造的Trie树结构。其中从根结点到红色方框叶子节点所经历的所有字符组成的串就是字符串集合X中的一个串。

注意这里有一个问题: 如果X集合中有一个串是另一个串的前缀呢? 比如,X集合中加入串bi。那么上图的Trie树在绿色箭头所指的内部结点i 就应该也标记成红色方形结点。这样话,一棵树的枝干上将出现两个连续的叶子结点(这是不合常理的)。

也就是说字符串集合X中不存在一个串是另外一个串的前缀 。如何满足这个要求呢?我们可以在X中的每个串后面加入一个特殊字符$(这个字符将不会出现在字母表中)。这样,集合X{bear$、bell$、…. bi$、bid$}一定会满足这个要求。

总结:一个存储长度为n,来自大小为d的字母表中s个串的集合X的标准trie具有性质如下:

  (1) 树中每个内部结点至多有d个子结点。

  (2) 树有s个外部结点。

  (3) 树的高度等于X中最长串的长度。

  (4) 树中的结点数为O(n)。

标准 Trie树的查找

对于英文单词的查找,我们完全可以在内部结点中建立26个元素组成的指针数组。如果要查找a,只需要在内部节点的指针数组中找第0个指针即可(b=第1个指针,随机定位)。时间复杂度为O(1)。

查找过程:假如我们要在上面那棵Trie中查找字符串bull (b-u-l-l)。

(1) 在root结点中查找第(‘b’-‘a’=1)号孩子指针,发现该指针不为空,则定位到第1号孩子结点处——b结点。

(2) 在b结点中查找第(‘u’-‘a’=20)号孩子指针,发现该指针不为空,则定位到第20号孩子结点处——u结点。

(3) … 一直查找到叶子结点出现特殊字符’$’位置,表示找到了bull字符串

如果在查找过程中终止于内部结点,则表示没有找到待查找字符串。

效率:对于有n个英文字母的串来说,在内部结点中定位指针所需要花费O(d)时间,d为字母表的大小,英文为26。由于在上面的算法中内部结点指针定位使用了数组随机存储方式,因此时间复杂度降为了O(1)。但是如果是中文字,下面在实际应用中会提到。因此我们在这里还是用O(d)。 查找成功的时候恰好走了一条从根结点到叶子结点的路径。因此时间复杂度为O(d*n)。

但是,当查找集合X中所有字符串两两都不共享前缀时,trie中出现最坏情况。除根之外,所有内部结点都自由一个子结点。此时的查找时间复杂度蜕化为O(d*(n^2))

标准 Trie树的Java代码实现:

    import java.util.ArrayList;  

    enum NodeKind{LN,BN};  
    /** 
     * Trie结点 
     */  
    class TrieNode{  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值