Trie,来源于(retrieval,取回,数据检索),是一种多叉树,用来存储字母表上的单词非常有用。


Trie经常用来存储动态集合(dynamic set)或者关联数组(associative array),其中的key通常是字符串。跟二叉搜索树不同的是,树中的结点不存储相关的key,而是靠结点在树中的位置来定义key。

在单词拼写检查或者一些能理解自然语言的程序中可以用来存储单词字典。

树中一个结点的所有子孙具有公共前缀。根结点root代表的是空字符串。不是所有的结点都有值。叶子结点和一部分非叶子结点关联着key,也就是所谓的值。

给定数据:
    an,ant,all,allot,alloy,aloe,are,ate,be
相应的trie:


如果字符串的字符集仅是a-z,那么一个节点最多有27个孩子结点(26个字母+1个终止符)。

实现

1、快速但浪费空间,在靠近树的底部将会有大量的null子树,这将浪费大量空间。

type trie = ^ node;
     node = record
               subtrie :array['a'..'z'] of trie;
               IsEndOfWord :boolean
            end;

2、每个结点用一个长度最长为27的链表来表示,链表中的元素用键值对<char,trie>来表示。在这种情况下,在叶子结点处浪费的空间比较少。

function find(word:string; length:integer; t:trie):boolean;
 
   function f(level:integer; t:trie):boolean;
   begin if level=length+1 then
            f:=t^.IsEndOfWord
         else if t^.subtrie[word[level]]=nil then
            f:=false
         else f:=f(level+1, t^.subtrie[word[level]])
   end{f};
 
begin find := f( 1, t )
end{find}

查找

def find(node, key):
    for char in key:
        if char not in node.children:
            return None
        else:
            node = node.children[char]
    return node.value

插入

algorithm insert(root : node, s : string, value : any):
    node = root
    i    = 0
    n    = length(s)
 
    while i < n:
        if node.child(s[i]) != nil:
            node = node.child(s[i])
            i = i + 1
        else:
            break
 
    (* append new nodes, if necessary *)
    while i < n:
        node.child(s[i]) = new node
        node = node.child(s[i])
        i = i + 1
 
    node.value = value

作为hash table的替换

相对于hash table,具有如下优点

1、在最坏情况下查找也具有O(m)(m是字符串的长度)的时间复杂度。优于hash table在最坏情况下(碰撞)的O(N)。

2、Trie没有碰撞。

3、当更多的key加入到Trie中时,不需要提供或者替换hash函数。

4、Trie可以提供按字母表排序的词条条目。

当然,也同样有缺点

1、如果数据保存在随机访问速度比主存慢的硬盘或者一些辅存中,Tries在查找数据时会比hash tables慢。

2、对于浮点数这种key,将会导致很长一串没什么意义的前缀。

3、一些Tries要求的空间比hash table大。因为在Trie中都是为单个的字符单独分配空间,而hash table为整个条目分配一个数据块。

排序

对一个集合的字典序排序可以通过Trie来实现:

1、将所有keys插入Trie。

2、先序遍历输出所有的keys。

这也是一种基数排序

参考资料

wikipedia

Tries前缀树的更多相关文章

  1. HDU1671——前缀树的一点感触

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1671 题目本身不难,一棵前缀树OK,但是前两次提交都没有成功. 第一次Memory Limit Exceed ...

  2. [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  3. 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树

    另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...

  4. trie树(前缀树)

    问题描述:   Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优 ...

  5. 【暑假】[实用数据结构]前缀树 Trie

    前缀树Trie Trie可理解为一个能够快速插入与查询的集合,无论是插入还是查询所需时间都为O(m) 模板如下: +; ; struct Trie{ int ch[maxnode][sigma_siz ...

  6. [Swift]LeetCode208. 实现 Trie (前缀树) | Implement Trie (Prefix Tree)

    Implement a trie with insert, search, and startsWith methods. Example: Trie trie = new Trie(); trie. ...

  7. 1042.D Petya and Array 前缀 + 树状数组

    11.19.2018 1042.D Petya and ArrayNew Point: 前缀 + 树状数组 :树状数组逐个维护前缀个数 Describe: 给你一个数组,一个标记数,问你有多少区间[l ...

  8. 算法进阶面试题07——求子数组的最大异或和(前缀树)、换钱的方法数(递归改dp最全套路解说)、纸牌博弈、机器人行走问题

    主要讲第五课的内容前缀树应用和第六课内容暴力递归改动态规划的最全步骤 第一题 给定一个数组,求子数组的最大异或和. 一个数组的异或和为,数组中所有的数异或起来的结果. 简单的前缀树应用 暴力方法: 先 ...

  9. 9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

    课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚 ...

  10. python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)

    python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容:(1)利用python中的dict实现Trie:(2) ...

随机推荐

  1. Django常见错误总结

    1 ImportError: No module named 'MySQLdb' 解决方法: . 安装pymysql模块 . 在app的__init__.py文件中写入以下内容 import pymy ...

  2. WPF中,如何屏蔽WebBrowser弹出的脚本错误窗口?

    WPF没有自带屏蔽这些窗口的方法或属性,可以使用反射的方法来屏蔽弹出脚本错误窗口: public void SuppressScriptErrors(WebBrowser wb, bool Hide) ...

  3. win10安装MAYA失败,怎么强力卸载删除注册表并重新安装

    一些搞设计的朋友在win10系统下安装MAYA失败或提示已安装,也有时候想重新安装MAYA的时候会出现本电脑windows系统已安装MAYA,你要是不留意直接安装MAYA,只会安装MAYA的附件或者直 ...

  4. MOOC(1)-使用pycharm新建Django项目、开发post接口

    https://www.cnblogs.com/liqu/p/9308966.html 1.安装Django的两种方式: > 1) pip install django 2)下载离线安装包,进入 ...

  5. haproxy笔记之六:负载均衡MySQL服务的配置示例

    #--------------------------------------------------------------------- # Global settings #---------- ...

  6. python中sorted和sorted 、reversed和reverse的使用。

    #encoding = utf-8 list = [1,8,3,6] print(list.sort()) #None print(list) #[1,3,6,8] print(sorted(list ...

  7. PHP PSR-2 代码风格规范

    代码风格规范 本篇规范是 PSR-1 基本代码规范的继承与扩展. 本规范希望通过制定一系列规范化PHP代码的规则,以减少在浏览不同作者的代码时,因代码风格的不同而造成不便. 当多名程序员在多个项目中合 ...

  8. MySQL远程访问失败的解决办法

    SQL连接预备知识:转载自https://jingyan.baidu.com/article/3ea51489e6cfbe52e61bba25.html问题:我想在另一个电脑通过navicat登陆本机 ...

  9. 查漏补缺:Vector中去重

    对于STL去重,可以使用<algorithm>中提供的unique()函数. unique()函数用于去除相邻元素中的重复元素(所以去重前需要对vector进行排序),只留下一个.返回去重 ...

  10. Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼.本文主要介绍 同域 和 跨域 两种不同场景单点登录的实现原理,并使用 Spring ...